Distorted output in wav file (Windows only)


#1

Getting some strange behaviour, Windows only.

We’re rendering output to a wav file from an Internal Plugin. The current way of doing this is to calculate the required length, set the size of an AudioSampleBuffer, and then in processBlock do:

        int numSamples = buffer.getNumSamples();

        if (isNonRealtime())
        {
            // Copy data to writeBuffer
            // Assume a stereo file
            writeBuffer.copyFrom(0, filePosition, buffer, 0, 0, numSamples);
            writeBuffer.copyFrom(1, filePosition, buffer, 1, 0, numSamples);
            //DBG ("Written " << numSamples << ", total " << filePosition << " samples to buffer");
        }

        filePosition += numSamples;

Finally when finished, it writes the file with

fileWriter->writeFromAudioSampleBuffer(writeBuffer, 0, (int) fileStats->fileLengthInSamples);
outputStream->flush();
fileWriter->flush();
fileWriter = nullptr;

This works fine on Mac, but on Windows we are getting some strange distortion on the rendered file. Any clues as to why this might be happening?


#2

Description of the distortion:

the difference between these files seem to be extremely periodical
and consistent
there is a certain amount of corrupted areas of similar lengths between constant intervals
several times per second of audio
let’s say ~50-100
per each second of audio

it’s just the left channel that is corrupted btw


#3

Let me guess: 512 samples per block and either 48 or 44.1 kHz?
48000 samples/ssecond / 512 samples = 93.75 distortions per second…

Is your plugin you were talking of maybe asynchronous, like a BufferingAudioSource? if so, you might be pulling the blocks faster than the buffering thread can supply new data.
That could also explain, why it is running on one plattform and not on the other, might be, that your mac is better equipped than your pc?

If you use a BufferingAudioSource you can add a semaphore for non realtime using bool BufferingAudioSource::waitForNextAudioBlockReady (const AudioSourceChannelInfo & info, const uint32 timeout).

But maybe it’s something completely different…

Good luck


#4

Thanks yes that sounds like a good clue… and yes it is 512 samples per buffer.

The audio source is a file, perhaps its trying to read too fast… but I would think that since read is synchronous that it would wait until it had read all the bytes before starting the next one?


#5

Of course, if you’re reading it directly, but like Daniel said, something like a BufferingAudioSource is designed for realtime use, and so won’t block.


#6

Ok - but if I am reading it directly with e.g.

    int numSamples = buffer.getNumSamples();
    fileReader->read(&buffer, 0, numSamples, filePosition, true, true);
    filePosition += numSamples;

in a processBlock, is there a chance that the data might get corrupted? Should it be buffered beforehand? This is for non-realtime rendering.


#7

No, unless another thread is writing on the same adress, but why should it…

That’s not needed and would introduce new chances for errors.

Did you try to write out that result without any processing inbetween? That might help to narrow the problem down.
Another idea, if you call all by hand, did you call prepareToPlay? I once forgot that and got obscure artefacts…


#8

So, after a fair bit of detective work, I found that on Windows only (Win7 on Parallels) it was reading around 440 samples, and the rest was distorted or junk… So changing the buffer size to 440 solved the issue.

I’d really like to understand whats going on here. Why does this not occur on realtime playback? I even added a 5ms wait on the offline rendering thread before each processBlock call - still has the same issue with reading the file at 512 or more samples per block.


#9

I saw 440 samples on windows as a common default value. But when you render offline, you actually don’t need to use the buffer size of the audio device. You can define any block size.
Just make sure, you use always the same numSamples.