开发者

Audio playback, creating nested loop for fade in/out

开发者 https://www.devze.com 2022-12-22 00:28 出处:网络
First time poster here. A quick question about setting up a loop here. I want to set up a for loop for the first 1/3 of the main loop that will increase a value from .00001 or similar to 1. So I can

First time poster here.

A quick question about setting up a loop here. I want to set up a for loop for the first 1/3 of the main loop that will increase a value from .00001 or similar to 1. So I can use it to multiply a sample variable so as to create a fade-in in this simple audio file playback routine.

So far it's turning out to be a bit of a head scratcher, any help greatfully recieved.

for(i=0; i < end && !feof(fpin); i+=blockframes) 
{ 
    samples = fread(audioblock, sizeof(sh开发者_运维问答ort), blocksamples, fpin); 
    frames = samples; 
    for(j=0; j < frames; j++)
    {   
        for (f = 0; f< frames/3 ;f++)
        {
            fade = fade--;
        } 
    output[j] = audioblock[j]/fade;
    }

    fwrite(output,sizeof(short), frames, fpoutput); 
} 

Apologies, So far I've read and re-write the file successfully. My problem is I'm trying to figure out a way to loop the variable 'fade' so it either increases or decreases to 1, so as I can modify the output variable.

I wanted to do this in say 3 stages: 1. From 0 to frames/3 to increace a multiplication factor from .0001 to 1 2. from frames 1/3 to frames 2/3 to do nothing (multiply by 1) and 3. For the factor to decrease again below 1 so as for the output variable to decrease back to the original point.

How can I create a loop that will increase and decrease these values over the outside loop?


I think you thought yourself into a corner, to say so. There's no need to create a nested loop to modify the fade gain, you can simply keep track of it through the loop and adapt it if necessary. Also, your variable naming of frames/samples seems a bit muddy to me, I hope I got that one right.

float fadeTime = 0.5f;
float outputGain = 0.0f;
float gainProgressionPerSample = 1.0f/(fadeTime*SAMPLERATE);
float fadeInStop = fadeTime*SAMPLERATE;
float fadeOutBegin;

for(i=0; i < end && !feof(fpin); i+=blockframes) 
{ 
    samples = fread(audioblock, sizeof(short), blocksamples, fpin); 
    fadeOutBegin = samples - fadeTime*SAMPLERATE;
    for(j=0; j < samples; j++)
    {
       if (j < fadeInStop)   
       {
         outputGain += gainProgressionPerSample;
       }
       // else is not used intentionally to allow fade in/out blending for short tracks
       if (j > fadeOutBegin)
       {
         outputGain -= gainProgressionPerSample;
       }
       output[j] = audioblock[j]*outputGain;
    }

    fwrite(output,sizeof(short), samples, fpoutput); 
} 


My first observation:

fade = fade--;

will not work, as it is equivalent to

int temp = fade - 1;
fade = fade;

This is how the post-increment operator works. So you should simply write

fade--;

instead (or --fade - whichever you prefer :-).

You should then build up your loops something like this:

for(j=0; j < frames/3; j++)
{   
    fade--;
    output[j] = audioblock[j]/fade;
}
for( ; j < 2*frames/3; j++)
{   
    output[j] = audioblock[j]/fade;
}
for( ; j < frames; j++)
{   
    fade++;
    output[j] = audioblock[j]/fade;
}


In modern processors there's no real reason not to use floating point for the math. It's more accurate and the performance is about the same as integer math. And if you are using floating point, there's not reason not to have all of your temp variables be doubles. declaring them as float actually costs performance.

This code will give you a linear fade in over (frames/3) samples

double gain = 0.0f;
double deltaGain = (1.0 - gain)/(frames/3);
for (int i=0; i < end && !feof(fpin); i += blockframes) 
{ 
    samples = fread(audioblock, sizeof(short), blocksamples, fpin); 

    j = 0;
    // do the fade in.
    for ( ; j < samples; ++j)
    {
       gain += deltaGain; // adjust the gain
       if (gain >= 1.0)
          break;

       output[j] = (short)(audioblock[j] * gain);
    }

    // copy the remainder.
    for ( ; j < samples; ++j)
       output[j] = audioblock[j];

    fwrite(output,sizeof(short), samples, fpoutput); 
} 

The basic trick is to figure out up front the starting point and ending point for your gain multiplier, then divide (end-start)/steps to get the amount that the gain should change for each sample. Then in your inner loop, adjusting the gain is just an addition. You can get an x-squared gain curve with just two additions in the inner loop. x-squared is a reasonable approximation of a log fade in which sounds more 'natural' since our ears hear in log scale.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号