2
$\begingroup$

I've done already some fade in or fade out effect in portaudio, but that is not working properly.

My callback function:

int SoundEngine::patestCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
{
    paData *callData = (paData*)userData;
    float *out = (float*)outputBuffer;
    float sample;
    unsigned long i;

    (void) timeInfo; /* Prevent unused variable warnings. */
    (void) statusFlags;
    (void) inputBuffer;

    for( i=0; i < framesPerBuffer; i++ )
    {
        sample = callData->sine[callData->phase++];
        *out++ = sample;

        if( callData->phase >= SE_TABLE_SIZE ) callData->phase -= SE_TABLE_SIZE;
    }
    return paContinue;
}

I've discovered that for whole stream it's easy to make fade out effect, by applying something like this:

if(callData->fadeFlag == true)
        {
            callData->toneCountdown--;
            sample *= (-cos(((float)(callData->toneCountdown - (callData->toneLength - callData->fadeOut)) / (float)callData->fadeOut) * M_PI) + 1.) * .5;
        }

But this is not working for me. If I have more than one sound at the moment, there are fading all sounds. At the moment I'm using callback function as I wrote above. callData->sine at the beginning contains only 0 to not produce any sound. Sound I'm adding by calling a member function playSound(). I am doing this in single thread - so I can use a lot of these functions at the same time - making a multiple sounds. How is working function playSound? There it is:

void SoundEngine::playSound(int instrument, int freq, int duration)
{
    if(instrument == 0)
    {
        for(int j=0; j<20; j++)
        {
            for(int i=0; i<SE_TABLE_SIZE; i++)
            {
                data.sine[i] += 0.01*sin(2 * M_PI * data.soundPitch[freq] * ((double)i/(double)SAMPLE_RATE));
            }
        }
        Pa_Sleep(duration);
        for(int j=0; j<20; j++)
        {
            for(int i=0; i<SE_TABLE_SIZE; i++)
            {
                data.sine[i] -= 0.01*sin(2 * M_PI * data.soundPitch[freq] * ((double)i/(double)SAMPLE_RATE));
            }
        }
    }
}

You are probably asking now: "What the hell that man done here?". I know that it's not a masterpiece of coding, but I'm newbie in sound programming, so I'm trying my best to learn it. For now I want just make it work as it should work.

Function playSound() is working great, but fade in/out is making some noise during fadeing. Fade effect is made by for(int j=0; j<20; j++) that's gradually volume up my sound. I think that modyfing data.sinedata couse those noises. When I slow down fade effect - it works perfectly, but too slow. I need fast fade in/out effect to eliminate noises at start and end of sound.

Can someone help me to apply fade in/out effect to my example?

$\endgroup$
  • $\begingroup$ Were you able to figure this out? If so, would you be willing to post your solution as an answer? I am also starting out with audio programming, and am curious. Thanks! $\endgroup$ – cxw Jun 15 '18 at 2:12
  • $\begingroup$ Unfortunately, I've not done it. I guess that the right way is to apply effect to stream instead of modyfing all samples in table. Good luck ;] $\endgroup$ – Lizard_Paszczyk Jun 18 '18 at 8:10
  • $\begingroup$ Thanks! You mentioned single-threaded, but does PortAudio create its own threads? I wonder if it's a race on data.sine. --- Not an answer, but I was able to get pop-free music playback by using a pa_ringbuffer: file reader; callback (audio-utsl repo). $\endgroup$ – cxw Jun 18 '18 at 12:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.