Pergunta

I did some research on sound synthesis and managed to write a very simple synthesizer. I've used the microsoft waveOut API. I wrote an interface to simplify the whole process. I can now initialize a (mono) audio stream and call setSample. So with a sampling rate of 44100 samples per second, setSample needs to be called at least 44100 times a second.

This works fine on my (quadcore) laptop, but on my parents' old dualcore vista, it stutters really bad. This is pretty weird: FL Studio runs quite smootly on my parents' machine, even when I use multiple effects on a more complicated synthesizer, while my code is fairly basic.

I have no idea what causes this behaviour. My code is far from optimized but so simple that I can hardly imagine that optimizing alone is the problem (unless I'm doing something which really slows the synthesis down).

The piece of code that could be a problem:

void AudioStream::setSample(float sample)
{
    unsigned int discreteSample = ((sampleSize > 1) ? 0 : amplitude) + ((float)amplitude * sample);

    for (unsigned int i = 0; i < sampleSize; i++)
    {
        data[pointr++] = (char)(discreteSample & 255);
        discreteSample = discreteSample >> 8;
    }

    if (pointr >= maxSize)
    {
        if (waveOutWrite(hWaveOut, firstHeader ? &header1 : &header2, firstHeader ? sizeof(header1) : sizeof(header2)) != MMSYSERR_NOERROR)
        { throw("Error writing to sound card!"); return; }

        pointr = 0;
        firstHeader = !firstHeader;

        if (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0) { throw("An error occured while waiting for sound to finish"); return; }

        unsigned char *temp;
        temp = data;
        data = play;
        play = temp;

        first = false;
    }
}

I think the conversion from a floating point value to a discrete sample may be troublesome. I use this to handle multiple sample sizes.

I also heard that waveOut may be software emulated (which would explain a lot), but I'm not sure if (or when, as in on what versions of windows or under which circumstances) this is the case and how much of a performance difference this would make.

I hope someone can help me.

Edit: source can be found here, executable here.

Foi útil?

Solução 2

WaveOut API and good performance are impossible together. Use something more suitable, ASIO or WASAPI if using Windows, or try Portaudio if you want to be cross-platform.

Outras dicas

Passing one sample at a time to waveOutWrite is going to be horribly inefficient, both at the level of your code and within the driver. It sets up a DMA transfer of a buffer, and if that buffer is one byte long it incurs all the overhead of switching buffers for every sample. I would send it at least one tenth of a second of samples in each call to waveOutWrite.

If you are looking for some very-easy audio library to make a simple synthesizer, i strongly recommend audiere http://audiere.sourceforge.net/ or BASS http://www.un4seen.com/.

The first one is quite outdated but at the same time one of the easiest one (that doesn't make it bad). I was able to write not that simple synthesizer with it. The second one, BASS, will do you good, in more complex projects too. It comes with very easy examples (and synthesizer is one of them). It's very easy to set up too.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top