立体乒乓延迟c ++

时间:2018-04-03 12:57:07

标签: c++ audio

我必须使用这些参数创建立体声乒乓延迟。

•延迟时间(0 - 3000毫秒)

•反馈(0 - 0.99)

•湿/干混合物(0 - 1.0)

我已经设法实现了立体声输入/输出和3个参数,但是在如何实现乒乓球方面苦苦挣扎。我在进程块中有这个代码,但它只在相反的通道中重放一次左右。是否有一种简单的方法可以循环使用它来反复回复,而不仅仅是一次或者说这不是实现乒乓的最佳方法。任何帮助都会很棒!

//ping pong implementation
for (int i = 0; i < buffer.getNumSamples(); i++)
{
    // Reduce the amplitude of each sample in the block for the
    // left and right channels
    //channelDataLeft[i] = channelDataLeft[i] * 0.5;
    // channelDataRight[i] = channelDataRight[i] * 0.25;

    if (i % 2 == 1) //if i is odd this will play
    {
    // Calculate the next output sample (current input sample + delayed version)
    float outputSampleLeft = (channelDataLeft[i] + (mix * delayDataLeft[readIndex]));
    float outputSampleRight = (channelDataRight[i] + (mix * delayDataRight[readIndex]));

    // Write the current input into the delay buffer along with the delayed sample
    delayDataLeft[writeIndex] = channelDataLeft[i] + (delayDataLeft[readIndex] * feedback);
    delayDataRight[writeIndex] = channelDataRight[i] + (delayDataRight[readIndex] * feedback);

    // Increment read and write index, check to see if it's greater than buffer length
    // if yes, wrap back around to zero
    if (++readIndex >= delayBufferLength)
        readIndex = 0;


    if (++writeIndex >= delayBufferLength)
        writeIndex = 0;

    // Assign output sample computed above to the output buffer
    channelDataLeft[i] = outputSampleLeft;
    channelDataRight[i] = outputSampleRight;
    }
    else //if i is even then this will play
    {
    // Calculate the next output sample (current input sample + delayed version swapped around from if)
    float outputSampleLeft = (channelDataLeft[i] + (mix * delayDataRight[readIndex]));
    float outputSampleRight = (channelDataRight[i] + (mix * delayDataLeft[readIndex]));

    // Write the current input into the delay buffer along with the delayed sample
    delayDataLeft[writeIndex] = channelDataLeft[i] + (delayDataLeft[readIndex] * feedback);
    delayDataRight[writeIndex] = channelDataRight[i] + (delayDataRight[readIndex] * feedback);

    // Increment read and write index, check to see if it's greater than buffer length
    // if yes, wrap back around to zero
    if (++readIndex >= delayBufferLength)
        readIndex = 0;


    if (++writeIndex >= delayBufferLength)
        writeIndex = 0;

    // Assign output sample computed above to the output buffer
    channelDataLeft[i] = outputSampleLeft;
    channelDataRight[i] = outputSampleRight;
    }
}

1 个答案:

答案 0 :(得分:0)

不确定为什么你有基于样本索引的模数和不同的行为。乒乓延迟应该有两个延迟缓冲器,每个通道一个。一个立体声声道的输入加上相反声道的延迟缓冲器的反馈应该被送入每个延迟。

这是一个很好的音频信号图形图像: http://2.bp.blogspot.com/-AQLw-KePSsw/WR4HG4wy9XI/AAAAAAAABo8/gW5fkhMZHWYtIyq_y2WoKDu3TY8sedI2ACK4B/s1600/Tutorial%2B42-Schema01.png

这是逻辑的一些伪代码:

float wetDryMix = 0.5f;
float wetFactor = wetDryMix;
float dryFactor = 1.0f - wetDryMix;
float feedback = 0.6f;

int sampleRate = 44100;
int sampleCount = sampleRate * 10;
float[] leftInSamples = new float[sampleCount];
float[] rightInSamples = new float[sampleCount];
float[] leftOutSamples = new float[sampleCount];
float[] rightOutSamples = new float[sampleCount];

int delayBufferSize = sampleRate * 3;
float[] delayBufferLeft = new float[delayBufferSize];
float[] delayBufferRight = new float[delayBufferSize];

int delaySamples = sampleRate / 2;
int delayReadIndex = 0;
int delayWriteIndex = delaySamples;


for(int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++) {
    //Read samples in from input
    leftChannel = leftInSamples[sampleIndex];
    rightChannel = rightInSamples[sampleIndex];

    //Make sure delay ring buffer indices are within range
    delayReadIndex = delayReadIndex % delayBufferSize;
    delayWriteIndex = delayWriteIndex % delayBufferSize;

    //Get the current output of delay ring buffer                              
    float delayOutLeft = delayBufferLeft[delayReadIndex];
    float delayOutRight = delayBufferRight[delayReadIndex];    

    //Calculate what is put into delay buffer. It is the current input signal plus the delay output attenuated by the feedback factor
    //Notice that the right delay output is fed into the left delay and vice versa
    //In this version sound from each stereo channel will ping pong back and forth
    float delayInputLeft = leftChannel + delayOutRight * feedback;
    float delayInputRight = rightChannel + delayOutLeft * feedback;

    //Alternatively you could use a mono signal that is pushed to one delay channel along with the current feedback delay
    //This will ping-pong a mixed mono signal between channels
    //float delayInputLeft = leftChannel + rightChannel + delayOutRight * feedback;
    //float delayInputRight = delayOutLeft * feedback;  

    //Push the calculated delay value into the delay ring buffers
    delayBufferLeft[delayWriteIndex] = delayInputLeft;
    delayBufferRight[delayWriteIndex] = delayInputRight;

    //Calculate resulting output by mixing the dry input signal with the current delayed output
    float outputLeft = leftChannel * dryFactor + delayOutLeft * wetFactor;
    float outputRight = rightChannel * dryFactor + delayOutRight * wetFactor;

    leftOutSamples[sampleIndex] = outputLeft;
    rightOutSamples[sampleIndex] = outputRight; 

    //Increment ring buffer indices
    delayReadIndex++;
    delayWriteIndex++;
}