Creating a sound file composed of smaller files - java

I am writing an app that takes Morse code, and plays it over the speakers.
Currently I am able to record audio over the microphone using this code:
public void startRecord() throws Exception{
if (record != null){
record.release();
}
File fileOut = new File(FILE);
if (fileOut != null){
fileOut.delete(); // delete any existing file at that location.
}
record = new MediaRecorder();
record.setAudioSource(MediaRecorder.AudioSource.MIC);
record.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
record.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
record.setOutputFile(FILE);
record.prepare();
record.start();
}
and i am able to generate morse code in a string formatted like this:
"-.... .---- -.... -.-. -.... ..... --... ---.."
I can iterate over this string using a for loop such as this:
char[] chars = message.toCharArray();
for (char ch : chars) {
//add to audio file
}
But I am not sure how to create a file out of strung together wav files. Ive seen some posts that mention setting the audio source as a file from the device, but Im not sure how to pick and choose which file and where to insert them, or how to compile it all into a single audio file.

Instead of creating a new sound file and playing that, it would probably be easier to just play each sound individually and when that sound finishes, you play the next sound, or you wait for a brief pause if it's a space.

I think you are trying to do this the harder way. What if you were to simply have the program read the first letter, play the appropriate sound, do the same for the next letter and so on throughout the text. I believe it is much simpler but if you are really set on trying to put it into one file you could have the program make an empty file but in the name it sets have the extension `.wav` or `.mp3` and do research into how they are encoded.

Related

Libgdx file handle.. reading a single line

I am trying to save and load files on a project that is coded on libgdx. Which means that i cant use a buffered reader because android wont read it.. and i cant move the project to android because it has to be in the core... after days and days or understanding all.. now i am trying File handing which should work right?? but i cant get it to read line by line.. it puts all the text in on string.. Help plzz.. also is my understanding correct and saving and loading is waaaay more complicated than it should be?? here is the code..
FileHandle handle = Gdx.files.local("words.txt");
String text = handle.readString();
words.add(text);
There are several ways to read this line by line. When your reading a file in using the LibGDX FileHandle API which include strings, byte arrays and into various readers; there are several ways to read the data in. I am assuming you have some form of dictionary in this file, with the words in a list separated by newlines? If this is the case you can take your existing string and split on the new line terminator.
FileHandle handle = Gdx.files.local("words.txt");
String text = handle.readString();
String wordsArray[] = text.split("\\r?\\n");
for(String word : wordsArray) {
words.add(word);
}
There's only really two newlines (UNIX and Windows) that you need to worry about.
FileHandle API
This is to all of you out there new to saving and loading and tired of looking for answers.. let me save u the trouble and days of research...
If you start a project in libgdx and want to save load on android.. Do not follow the buffered reader or inputstreamer or any of these tutorials THEY WILL NOT WORK because for some reason android cannot read inside the assest folder.. it will work on ur desktop version only..
if you are using android studios alone then go ahead with the try catch buffered or file or inputstreamer..
Also the Context.. asset manager.. and that route WILL NOT WORK because the project has to be in your android folder not core to use these libraries..
ELSE FOLLOW THE ABOVE METHOD..
classpath.. internal.. external .. or local ... depending on where you store ur file!!!.. your welcome
String str ="";
StringBuffer buf = new StringBuffer();
FileHandle file = Gdx.files.internal("text.txt");
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(file.read()));
if (is != null) {
while ((str = reader.readLine()) != null) {
buf.append(str + "\n" );
}
}
} finally {
try { is.close(); } catch (Throwable ignore) {}
}

File Extension - Use it for files. (.Mp3 and .Wav)

I manage to make a program that could understand mp3 in Java (by jaco.mp3 jar) and it works. However this means that the .Wav files doesn't work of course. So I fixed so that I could use the Wav but the problem will then be that I can't use the mp3 then. so I found out that I could use the File Extension and my idea was to make like this:
If the last 3 or 4 letters ends with .mp3 then do the mp3 method, if its .Wav then to Wave method. but I don't really know how to manage it together, I was thinking more like a Switch-statement. But I really never worked with File extension before and could need som help with that!
However this is my mp3 method that is like this right now:
public void Choose() {
String userDir = System.getProperty("user.home");
JFileChooser fileChooser = new JFileChooser(userDir +"/Desktop");
int returnValue = fileChooser.showOpenDialog(null);
if (returnValue == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
System.out.println(selectedFile.getName());
mp3_player = new MP3Player(selectedFile);
lblPlayURL.setText(selectedFile.getName());
}
}
}
as you can see I have a JFileChooser where I pick the song I want of course and I still want to do it, only that the different is now it should work both as .Wav and .mp3. But I don't really know how to go further with it. so any help is needed from you guys! :)
Before people is trying to give any suggestions from a thread that says Playing .Wav and .Mp3. I would just say first that I have read it and there is only answers about each of them, Only mp3 or the .Wav. not both. so thats why I created this thread because I need help!
You can perhaps check if the file path ends with MP3 or WAV and have an if statement to run different programs depending on the condition.
This can be done like so:
String ext = selectedFile.getPath();
if(ext.endsWith(".wav"))
{
// A WAV file was chosen
}
else if(ext.endsWith(".mp3"))
{
// An MP3 file was chosen
}
else
{
// Something else was chosen
}
EDIT: This method together with Bogdan's answer is probably your best bet.
Add FileFilter rules to your JFileChooser to match .mp3 and .wav files:
fileChooser.addChoosableFileFilter(new FileTypeFilter(".mp3", "MP3 Files"));
fileChooser.addChoosableFileFilter(new FileTypeFilter(".wav", "WAV files"));
How to add file filter for JFileChooser dialog.

One use Java audio?

I am building a speech synthesizer, and everything works except the audio. I have a list of phonemes that are stored as .wav files, and I am calling them with AudioInputStreams, but they won't repeat. I have no idea what could be the issue, so any help would be appreciated.
The code that initializes a HashMap full of phones is
for(File phone : listOfFiles){
String path = phone.getPath();
if(path.startsWith(".")){continue;}
path = path.replace(".wav", "").replace("phones/", "");
AudioInputStream clip1 = AudioSystem.getAudioInputStream(phone);
phonemes.put(path,clip1);
}
and the code that combines and outputs the sound is
public void speak(String[] input){
AudioInputStream phrase = phonemes.get(input[0]);
AudioInputStream phone;
int x = input.length;
for(int i=1; i<input.length; i++){
phone = phonemes.get(input[i]);
phrase = new AudioInputStream(new SequenceInputStream(phrase, phone), phrase.getFormat(), phrase.getFrameLength() + phone.getFrameLength());
}
try {
Clip clip = AudioSystem.getClip();
clip.open(phrase);
clip.start();
} catch (Exception e) {
e.printStackTrace();
}
}
To replay a Clip, you have to stop it and reposition it, then start it. I don't think you can close and reopen a given Clip. But attempts to do that should have generated a LineUnavailable exception, and you say you got no exceptions.
To troubleshoot, I'd first verify that it is possible to play the .wav files prior to placing them in the hash table. Sometimes an unexpected format (e.g., 24-bit or 32-bit encoding, or big-endian rather than little-endian) can lead to .wav files not playing.
If you are trying to concatenate a series of clips or audio data into a single clip, that could also be problematic. I think that AudioInputStream expects a single set of "header" data from the .wav file, but the SequenceInputStream could in effect be sending multiple "headers", one for each source file. I've never seen concatenation attempted like that before.
You might need to make your own data storage for the raw audio for each phoneme, and then build your combined phonemes from that rather than directly from .wav files. Instead of loading to Clips, load the raw PCM from the AudioInputStream into byte arrays. To output the raw audio bytes, you can use a SourceDataLine.

Creating a .txt file from scratch

I'm working on a microcontroller and I'm trying to write some data from some sensors into a .txt file on the SDcard and later on place the sd card in a card reader and read the data on the PC.
Does anyone know how to write a .txt file from scratch for a FAT32 file system? I don't have any predefined code/methods/functions to call, I'll need to create the code from nothin.
It's not a question for a specific programming language, that is why I tagged more than one. I can later on convert the code from C or Java to my programming language of choice. But I can't seem to find such low level methods/functions in any type of language :)
Any ideas?
FatFs is quite good, and highly portable. It has support for FAT12, FAT16 and FAT32, long filenames, seeking, reading and writing (most of these things can be switched on and off to change the memory footprint).
If you're really tight on memory there's also Petit FatFs, but it doesn't have write support by default and adding it would take some work.
After mounting the drive you'd simply open a file to create it. For example:
FATFS fatFs;
FIL newFile;
// The drive number may differ
if (f_mount(0, &fatFs) != FR_OK) {
// Something went wrong
}
if (f_open(&newFile, "/test.txt", FA_WRITE | FA_OPEN_ALWAYS) != FR_OK) {
// Something went wrong
}
If you really need to create the file using only your own code you'll have to traverse the FAT, looking for empty space and then creating new LFN entries (where you store the filename) and DIRENTs (which specify the clusters on the disk that will hold the file data).I can't see any reason for doing this except if this is some kind of homework / lab exercise. In any case you should do some reading about the FAT structure first and return with some more specific questions once you've got started.
In JAVA you can do like this
Writer output = null;
String text = "This is test message";
File file = new File("write.txt");
output = new BufferedWriter(new FileWriter(file));
output.write(text);
output.close();
System.out.println("Your file has been written");

Using a button to export sqlite db to an excel-readable file (perhaps csv)?

I adapted this tutorial (http://www.screaming-penguin.com/node/7749) to an Android app I've built to allow for a button press to export the current database to the user's sdcard. It works flawlessly.
But I'm afraid that users of my app would be unfamiliar with the db file, and I'm looking for a way to convert that to a more user-friendly format. I came across this thread (http://groups.google.com/group/android-beginners/browse_thread/thread/4e53ebca14daecfc), which recommends "querying data from the database and writing the data into a csv file."
I was hoping someone could point me in the right direction to begin figuring out how to do this. I'm finding it hard to track down more information about the specific method.
Or does it make more sense to just explain in a short "about" how to read and access .db files?
Thanks
EDIT: I also have a question about the sqlite export process, which I think I'll just ask here rather than create a new question. Is there a way to modify the code below so that each export would receive either a string representation of the date or just a single numeral appended to it? Right now if you export a second time, it automatically overwrites the old file. Thanks.
protected Boolean doInBackground(final String... args) {
File dbFile = new File(Environment.getDataDirectory() +
"/data/com.example.example/databases/data");
File exportDir = new File(Environment.getExternalStorageDirectory(), "exampledata");
if (exportDir.exists()) {
exportDir.mkdirs();
}
File file = new File(exportDir, dbFile.getName());
try {
file.createNewFile();
this.copyFile(dbFile, file);
return true;
} catch(IOException e) {
Log.e(MyApplication.APP_NAME, e.getMessage(), e);
return false;
}
}
I was hoping someone could point me in the right direction to begin figuring out how to do this.
To read in the data, use rawQuery().
To write the data, use Java I/O. There are also open source CSV libraries for Java that may work on Android.
Is there a way to modify the code below so that each export would receive either a string representation of the date or just a single numeral appended to it?
Use string concatenation to add whatever you want to the filename.
Also, please get rid of:
File dbFile = new File(Environment.getDataDirectory() +
"/data/com.example.example/databases/data");
and replace it with:
File dbFile=getDatabasePath("data");

Categories