2015-02-26 2 views
0

Я пытаюсь смешать некоторые сэмплы с помощью следующего алгоритма:алгоритм микширования аудио изменение объема

short* FilterGenerator::mixSources(std::vector<RawData>rawsources, int numframes) 
{ 
short* output = new short[numframes * 2]; // multiply 2 for channels 

for (int sample = 0; sample < numframes * 2; ++sample) 
{ 
    for (int sourceCount = 0; sourceCount < rawsources.size(); ++sourceCount) 
    { 
     if (sample <= rawsources.at(sourceCount).frames * 2) 
     { 
      short outputSample = rawsources.at(sourceCount).data[sample]; 
      output[sample] += outputSample; 
     } 
    } 
} 

// post mixing volume compression 
for (int sample = 0; sample < numframes; ++sample) 
{ 
    output[sample] /= (float)rawsources.size(); 
} 

return output; 
} 

Я получаю выход я хочу за то, что, когда один из источников сделано, другой, кроме источники начинают играть громче. Я знаю, почему это так, но я не знаю, как правильно его решить.

Кроме того, это скриншот из Audacity с выхода аудио I: Audacity Screenshot

Как вы можете видеть, что есть определенно что-то не так. Вы можете видеть, что звук больше не имеет нуля в центре, и вы можете видеть, как звук становится громче, как только один из источников проигрывается.

Больше всего я хотел бы исправить проблему с громкостью, но любые другие хитрости, которые я могу сделать, очень ценятся!

Дополнительная информация: Я знаю, что этот код не позволяет использовать моно источники, но это нормально. Я только собираюсь использовать стереоперемещенные аудио-образцы.

+0

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

+0

Это заголовок в файл. Я редактирую аудио не в реальном времени. Я знаю, что я могу сделать некоторые вещи более результативными, но сейчас это не проблема. Он делает то, что я хочу очень быстро на данный момент – Dries

+0

@JohnK: Не потейте. Современные распределители удивительно эффективны, а звук очень медленный по сравнению с процессорами. Выделение 1 кБ-буфера легко в тысячу раз быстрее, чем его воспроизведение. – MSalters

ответ

1

Обычно смешивание не делит на количество источников. Это означает, что сочетание обычной дорожки с немой дорожкой может уменьшить ее амплитуду в два раза. Если вы хотите, вы можете в конечном итоге нормализовать трек, чтобы он находился в его диапазоне.

код не проверяется, могут быть ошибки:

#include <algorithm> // for std::max 
#include <cmath>  // for std::fabs 

short* FilterGenerator::mixSources(std::vector<RawData>rawsources, int numframes) 
{ 
    // We can not use shorts immediately because can overflow 
    // I use floats because in the renormalization not have distortions 
    float *outputFloating = new float [numframes * 2]; 

    // The maximum of the absolute value of the signal 
    float maximumOutput = 0; 

    for (int sample = 0; sample < numframes * 2; ++sample) 
    { 
     // makes sure that at the beginning is zero 
     outputFloating[sample] = 0; 

     for (int sourceCount = 0; sourceCount < rawsources.size(); ++sourceCount) 
     { 
      // I think that should be a '<' 
      if (sample < rawsources.at(sourceCount).frames * 2) 
       outputFloating[sample] += rawsources.at(sourceCount).data[sample]; 
     } 

     // Calculates the maximum 
     maximumOutput = std::max (maximumOutput, std::fabs(outputFloating[sample])); 
    } 

    // A short buffer 
    short* output = new short [numframes * 2]; // multiply 2 for channels 

    float multiplier = maximumOutput > 32767 ? 32767/maximumOutput : 1; 

    // Renormalize the track 
    for (int sample = 0; sample < numframes * 2; ++sample) 
     output[sample] = (short) (outputFloating[sample] * multiplier); 

    delete[] outputFloating; 
    return output; 
} 
+0

Значит, вы оставите это подразделение и затем используете какое-то сжатие? – Dries

+0

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

+0

Так что я должен был бы иметь какой-то линейный динамический диапазон Сжатие? (реакция на комментарий ниже) – Dries

0

Поскольку вы складывая все в short, прежде чем делить, вы, вероятно, получить переполнение. Вам нужно добавить к посреднику, который больше. Кроме того, окончательное масштабирование не должно зависеть от количества выборок, оно должно быть постоянным - определить его до, который вы называете своей функцией.

short* FilterGenerator::mixSources(std::vector<RawData>rawsources, int numframes, double gain = 0.5) 
{ 
    short* output = new short[numframes * 2]; // multiply 2 for channels 

    for (int sample = 0; sample < numframes * 2; ++sample) 
    { 
     long newSample = 0; 
     for (int sourceCount = 0; sourceCount < rawsources.size(); ++sourceCount) 
     { 
      if (sample <= rawsources.at(sourceCount).frames * 2) 
      { 
       short outputSample = rawsources.at(sourceCount).data[sample]; 
       newSample += outputSample; 
      } 
     } 
     output[sample] = (short)(newSample * gain); 
    } 

return output; 
} 
+0

А что, если 'newSample * gain' все еще переполняется? Это решение просто неправильно ... – ciamej

0

Вам действительно не нужно выполнять «сжатие объемного смешивания». Просто добавьте все источники и не позволяйте сумме переполняться. Это должно работать:

short* FilterGenerator::mixSources(std::vector<RawData>rawsources, int numframes) 
{ 
short* output = new short[numframes * 2]; // multiply 2 for channels 

for (int sample = 0; sample < numframes * 2; ++sample) 
{ 
    long sum = 0; 
    for (int sourceCount = 0; sourceCount < rawsources.size(); ++sourceCount) 
    { 
     if (sample < rawsources.at(sourceCount).frames * 2) 
     { 
      short outputSample = rawsources.at(sourceCount).data[sample]; 
      sum += outputSample; 
      output[sample] += outputSample; 
     } 
     if (sum > 32767) sum = 32767; 
     if (sum < -32768) sum = -32768; 
     output[sample] = (short)sum; 
    } 
} 

return output; 
} 
Смежные вопросы