Функция постепенного исчезновения звука между изменениями частоты дискретизации

StackOverflow https://stackoverflow.com//questions/20037947

Вопрос

Я пытаюсь создать простую функцию, которая будет уменьшать громкость звука в буфере (например, затухание) на каждой итерации через буфер.Вот моя простая функция.

double iterationSum = 1.0;

double iteration(double sample)
{
 iterationSum *= 0.9;

 //and then multiply that sum with the current sample.
 sample *= iterationSum;
 return sample;
}

Это работает нормально, если установлено значение частоты дискретизации 44100 кГц, но проблема, с которой я столкнулся, заключается в том, что если частота дискретизации для примера изменена на 88200 кГц, то каждый раз следует уменьшать громкость только наполовину, потому что частота дискретизации в два раза больше и будет в противном случае завершите «затухание» в перерыве между таймами, и я попытался использовать такой коэффициент, как 44100/88200 = 0,5, но это никоим образом не сделает половину шага меньше.

Я застрял в этой простой проблеме, и мне нужно руководство, которое поможет мне разобраться. Что я могу сделать, чтобы сделать это на полшага на каждой итерации, поскольку эта функция вызывается, если частота дискретизации изменяется во время выполнения программы?

С уважением, Морган

Это было полезно?

Решение

Самый надежный способ затухания независимо от частоты дискретизации — это отслеживать время с момента начала затухания и использовать явный fadeout(time) функция.

Если по какой-то причине вы не можете этого сделать, вы можете установить скорость экспоненциального затухания на основе частоты дискретизации следующим образом:

double decay_time = 0.01; // time to fall to ~37% of original amplitude
double sample_time = 1.0 / sampleRate;
double natural_decay_factor = exp(- sample_time / decay_time);
...
double iteration(double sample) {
    iterationSum *= natural_decay_factor;
    ...
}

Причина ~37% это потому что exp(x) = e^x, где e — база «натурального логарифма», а 1/e ~ 0.3678....Если вам нужен другой коэффициент затухания для вашего времени затухания, вам нужно масштабировать его на константу:

// for decay to 50% amplitude (~ -6dB) over the given decay_time:
double halflife_decay_factor = exp(- log(2) * sample_time / decay_time);

// for decay to 10% amplitude (-20dB) over the given decay_time:
double db20_decay_factor = exp(- log(10) * sample_time / decay_time);

Другие советы

Я не уверен, если я понял, но как насчет чего-то вроде этого:

public void fadeOut(double sampleRate)
{
    //run 1 iteration per sec?
    int defaultIterations=10;

    double decrement = calculateIteration(sampleRate, defaultIterations);

    for(int i=0; i < defaultIterations; i++)
    {

        //maybe run each one of these loops every x ms?
        sampleRate = processIteration(sampleRate, decrement);
    }
}


public double calculateIteration(double sampleRate, int numIterations)
{
    return sampleRate/numIterations;
}


private double processIteration(double sampleRate, double decrement)
{
    return sampleRate -= decrement;
}
.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top