Программно увеличить высоту массива аудиосэмплов - PullRequest
11 голосов
/ 01 марта 2011

Привет, добрые люди из мира аудиокомпьютеров,

У меня есть массив сэмплов, которые представляют запись.Допустим, это 5 секунд при 44100 Гц.Как бы я проиграл это с увеличенным шагом?И можно ли динамически увеличивать и уменьшать высоту тона?Например, медленно увеличивайте высоту тона, чтобы удвоить скорость, а затем отступите.

Другими словами, я хочу взять запись и воспроизвести ее так, как если бы она «царапалась» ди-джеем

* 1006.* Псевдокод всегда приветствуется.Я буду писать это на языке C.

Спасибо,


РЕДАКТИРОВАТЬ 1

Позвольте мне уточнить мои намерения.Я хочу сохранить воспроизведение на частоте 44100 Гц, поэтому мне нужно манипулировать семплами перед воспроизведением .Это также потому, что я хотел бы смешать звук с увеличенной высотой звука со звуком, который работает с нормальной скоростью .

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


EDIT 2

Кроме того, я хотел бы сделать это сам.Никаких библиотек, пожалуйста (если только вы не чувствуете, что я могу выбрать код и найти что-нибудь интересное).


РЕДАКТИРОВАТЬ 3

Пример кода, написанного на C, который принимает 2 аргумента (массив выборок и коэффициент основного тона), а затем возвращает массивновый звук был бы фантастическим!


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



AWARD OF BOUNTY

Честно говоря, я бы хотел распределить вознаграждение по нескольким различным ответам, поскольку их было довольно мало, что я считал суперполезно.Особые пожелания Дэниелу за передачу мне кода, а AShelly и Hotpaw2 за такие подробные ответы.

В конечном счете, хотя я использовал ответ от на другой вопрос SO , на который ссылается специалист по обработке данных, и поэтому награда достается ему.

Еще раз спасибо всем!

Ответы [ 6 ]

10 голосов
/ 19 марта 2011

Взгляните на статью "Слон" в ответе Носредны на этот (очень похожий) ТАК вопрос: Как вы выполняете бикубическую (или другую нелинейную) интерполяцию повторно дискретизированных аудиоданных?

Примеры реализации представлены начиная со страницы 37, и для справки ответ А.Шелли соответствует линейной интерполяции (на той же странице). С небольшими изменениями, любая из других формул в документе может быть подключена к этой структуре.

Для оценки качества данного метода интерполяции (и понимания потенциальных проблем с использованием «более дешевых» схем), посмотрите на эту страницу:

http://www.discodsp.com/highlife/aliasing/

Для большей теории, чем вы, вероятно, хотите иметь дело (с исходным кодом), это также хорошая справка:

https://ccrma.stanford.edu/~jos/resample/

8 голосов
/ 01 марта 2011

Один из способов - сохранить индекс с плавающей запятой в исходной волне и смешать интерполированные выборки в выходной волне.

//Simulate scratching of `inwave`: 
// `rate` is the speedup/slowdown factor. 
// result mixed into `outwave`
// "Sample" is a typedef for the raw audio type.
void ScratchMix(Sample* outwave, Sample* inwave, float rate)
{
   float index = 0;
   while (index < inputLen)
   {
      int i = (int)index;          
      float frac = index-i;      //will be between 0 and 1
      Sample s1 = inwave[i];
      Sample s2 = inwave[i+1];
      *outwave++ += s1 + (s2-s1)*frac;   //do clipping here if needed
      index+=rate;
   }

}

Если вы хотите изменить rateна лету, вы можете сделать это тоже.

Если это создает шумовые артефакты при скорости> 1, попробуйте заменить *outwave++ += s1 + (s2-s1)*frac; этой техникой ( из этого вопроса )

*outwave++ = InterpolateHermite4pt3oX(inwave+i-1,frac);

, где

public static float InterpolateHermite4pt3oX(Sample* x, float t)
{
    float c0 = x[1];
    float c1 = .5F * (x[2] - x[0]);
    float c2 = x[0] - (2.5F * x[1]) + (2 * x[2]) - (.5F * x[3]);
    float c3 = (.5F * (x[3] - x[0])) + (1.5F * (x[1] - x[2]));
    return (((((c3 * t) + c2) * t) + c1) * t) + c0;
}

Пример использования метода линейной интерполяции в «Windows Startup.wav» с коэффициентом 1,1.Оригинал вверху, ускоренная версия внизу:

1.1x интерполяция

Может быть, математически не идеально, но звучит так, как должно, и должно хорошо работать для нужд ОП ..

3 голосов
/ 24 марта 2011

Если вы хотите, чтобы это было легко сделано, см. Предложение AShelly [править: попробуйте сначала в любом случае] .Если вам нужно хорошее качество, вам в основном нужен фазовый вокодер .

Самая основная идея фазового вокодера - найти частоты, из которых состоит звук, изменить эти частоты по мере необходимости иповторно синтезировать звук.Таким образом, жестокое упрощение будет:

  1. запустить БПФ
  2. изменить все частоты с коэффициентом
  3. запустить обратное БПФ

Если выСобираясь реализовать это самостоятельно, вам определенно следует прочитать подробное объяснение того, как работает фазовый вокодер .Алгоритм действительно нуждается в гораздо большем количестве соображений, чем приведенное выше трехэтапное упрощение.

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

3 голосов
/ 02 марта 2011

Да, это возможно.

Но это не маленький объем псевдокода.Вы запрашиваете алгоритм изменения шага по времени, который представляет собой довольно большой и сложный объем кода DSP для достойных результатов.

Вот краткий обзор растяжения шага из DSP Dimensions .Вы также можете использовать Google для алгоритмов фазового вокодера.

ADDED:

Если вы хотите «поцарапать», как ди-джей может сделать с LP на физическом проигрывателе, вы неНе нужно изменение шага по времени.Царапание изменяет высоту и скорость воспроизведения на одну и ту же величину (не независимо, что потребовало бы изменения шага по времени).

И полученный массив не будет иметь одинаковую длину, но будет короче или длиннеебез изменения высоты тона / скорости.

Вы можете изменить высоту тона, а также заставить звук воспроизводиться быстрее или медленнее в том же соотношении, просто передискретизировав сигнал, используя правильно отфильтрованную интерполяцию.Просто переместите каждую точку выборки, а не на 1,0, путем добавления числа с плавающей запятой к желаемому изменению скорости, затем отфильтруйте и интерполируйте данные в этой точке.Интерполяция с использованием оконного ядра Sinc-интерполяции с частотой перехода фильтра нижних частот ниже нижней исходной и интерполированной локальной частоты дискретизации будет работать достаточно хорошо.Поиск "оконной интерполяции Sinc" в сети возвращает множество подходящих результатов.

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

0 голосов
/ 01 марта 2011

Это помогло мне с передискретизацией, а это то же самое, что вам нужно, просто посмотрите с противоположной стороны.

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

0 голосов
/ 01 марта 2011

Уменьшить и увеличить высоту звука так же просто, как воспроизвести семпл с более низкой или более высокой частотой, чем 44,1 кГц.Это приведет к более медленной / быстрой записи звука, но вам нужно будет добавить «царапины» реальных записей.

...