Как визуализировать аудиоданные?

Я хотел бы иметь что-то похожее на это. Два разных цвета не являются обязательными.

смелость на mac http://audacity.sourceforge.net/about/images/audacity-macosx.png

У меня уже есть аудиоданные (один образец/миллисекунда) из стерео wav в двух внутренних массивах, по одному для левого и правого каналов. Я сделал несколько попыток, но они не выглядят нигде не столь же ясными, как мои, мои попытки попадают в spikey или компактный кусок.

Любые хорошие предложения? Я работаю в С#, но psuedocode в порядке.

Предположим, что

  • функция DrawLine (цвет, x1, y1, x2, y2)
  • два массива int с данными справа [] и слева [] длины L
  • значения данных между 32767 и -32768

Если вы сделаете какие-либо другие предположения, просто напишите их в своем ответе.

for(i = 0; i < L - 1; i++) {
  // What magic goes here?
}

Так получилось, когда я применил решение Han. (только один канал)
alt text http://www.imagechicken.com/uploads/1245877759099921200.jpg

Ответ 1

Вероятно, у вас будет более одного образца для каждого пикселя. Для каждой группы образцов, отображенных на один пиксель, вы можете провести (вертикальный) сегмент линии от минимального значения в группе образцов до максимального значения. Если вы увеличиваете масштаб до 1 образца на пиксель или меньше, это больше не работает, а "хорошим" решением будет отображать интерполированные значения sinc. Поскольку DrawLine не может рисовать один пиксель, возникает небольшая проблема, когда минимальные и максимальные значения одинаковы. В этом случае вы можете скопировать одно пиксельное изображение в нужную позицию, как в приведенном ниже коде:

double samplesPerPixel = (double)L / _width;
double firstSample = 0;
int endSample = firstSample + L - 1;
for (short pixel = 0; pixel < _width; pixel++)
{
    int lastSample = __min(endSample, (int)(firstSample + samplesPerPixel));
    double Y = _data[channel][(int)firstSample];
    double minY = Y;
    double maxY = Y;
    for (int sample = (int)firstSample + 1; sample <= lastSample; sample++)
    {
        Y = _data[channel][sample];
        minY = __min(Y, minY);
        maxY = __max(Y, maxY);
    }
    x = pixel + _offsetx;
    y1 = Value2Pixel(minY);
    y2 = Value2Pixel(maxY);
    if (y1 == y2)
    {
        g->DrawImageUnscaled(bm, x, y1);
    }
    else
    {
        g->DrawLine(pen, x, y1, x, y2);
    }
    firstSample += samplesPerPixel;
}

Обратите внимание, что Value2Pixel масштабирует значение выборки до значения пикселя (в направлении y).

Ответ 2

Для этого вы можете заглянуть в R. У меня мало опыта, но он в основном используется в сценариях статистического анализа/визуализации. Я был бы удивлен, если бы у них не было некоторой функции сглаживания, чтобы избавиться от крайностей, как вы упомянули.

И вам не составит труда импортировать ваши данные. Вы можете не только читать текстовые текстовые файлы, но также легко расширяться с помощью C, поэтому, возможно, есть и какой-то интерфейс С#.