Hi everybody.
I’m writing an app that’s supposed to write all active audio outputs to mono wav-files. I tried the followingto create my files
[code]outputFiles[128];
int outputChannel=0;
int i=0;
while ( outputChannel != -1 )
{
// find next active output
outputChannel = audioDeviceManager->getOutputChannels().findNextSetBit(outputChannel);
if ( outputChannel != -1 ) // we have an active output at this index
{
String fileName = String("c:\\test\\channel");
fileName += String(outputChannel+1); // add channel-number
fileName += String(".wav");
outputFiles[i] = File(fileName);
outputChannel++;
i++;
}
}[/code]
and in the thread that’s doing the actual writing
for (int i=0; i<buffer->getNumChannels(); i++) // loop over all available channels
{
// more code...
outputTo = outputFiles[i].createOutputStream();
writer = wavFormat->createWriterFor(outputTo, 44100, 1, 16, NULL, 0);
oneChannelBuffer.writeToAudioWriter( writer, 0, OneChannelBuffer.getNumSamples());
delete writer;
oneChannelBuffer.clear();
}
Problem is that I can’t open the files in Audacity. I can only import them as raw data and there is a crackle in the files (about 20-22 Samples) at the positions I guess, where the writer continued to write to the file.
any suggestions what I’m doing wrong? Thanks for your help
Looks to me you are creating a raw binary file(no wave header) which explains why Audacity needs to read it in as raw.
Take a look at juce_WavAudioFormat.h there is a createWriterFor function that “Tries to create an object that can write to a stream with this audio format.”
I haven’t used it myself(yet!) but in the constructor/deconstructor(for updating after writing audio samples) of WavAudioFormatWriter you can it creating the proper header. The writer also seems to take care of converting from float to little/big endian ints as well…
hm, I am actually using the createWriterFor function, as you can see. In first tests, when writing only one file, I created the outputStream and writer in the constructor and then repeatedly wrote to the file and there was no problem. The errors occured when I started to create and delete stream and writer during the loop. So I guess, I’m wrong there.
Most likely you’re re-using a deleted writer or deleting an input stream twice, or something like that. Or if you’re using threads, there could be more than one trying to write the same file.
I use only one thread for file writing, which repeatedly should create and destroy a writer to the destination file. I record the output of processed audio, so i append audio data to the files when it’s available.
At this point the crackle appears (so it’s the first 22 samples, too). I had a closer look at the waveforms and saw that they are all the same. I mean the crackle, in all files.
So using only one thread to write, I don’t think it’s a thread problem. The data is read from audioDeviceOutput and buffered to a multichannel AudioSampleBuffer, copied to a single Channel AudioSampleBuffer and sent to the audioWriter, so I don’t have or delete any input streams.
Thought about re-using a deleted writer, but I think I’m creating a new one, ain’t I?
Thanks for your help,
Ingo
Oh, well you can’t use these classes to append to a file - not sure how you imagined that would work! Effectively, you’re sticking one wave file on the end of another, so obviously you’ll get a “crackle” - that’s the second file’s header bytes!
??? Only if you’re going to manually write the file yourself.
You can’t just stuff extra bytes on the end of a file and expect it to work - the header needs to contain info about the file size. If you’re streaming to a file, just keep the writer open and keep writing to it until you’re finished.
ok, understood. can I create the writers in an array like I did it with the files then. At the moment I’ve got 128 outputChannels and this number will possibly even increase. That’s the reason why I came to the stupid idea of creating the write in loop when i actually want to write some audio. I hoped to have it working with one writer instead of 128…
Any other suggestions to solve this problem more elegantly?
this is how i did it, check the bool ThorWorkerThread::ogg2wav (InputStream *in, OutputStream *out) method, it works for me and my little kitty: http://code.google.com/p/thor-v2/