Как я могу сэмплировать файл wav с использованием AS3? - PullRequest
3 голосов
/ 17 декабря 2009

Я пытаюсь увеличить частоту 16-разрядного файла WAV 8000 Гц до 11025 Гц в AS3. На данный момент меня не беспокоит применение фильтров нижних частот, которые, как я знаю, мне в конечном итоге понадобятся.

Я ссылаюсь на эту вики-страницу .

Вот что я сделал до сих пор:

  1. Рассчитано наименьшее общее кратное 3528000
  2. Расчетный L будет 441
  3. Рассчитано М, чтобы быть 320
  4. Добавлено 440 нулей между выборками
  5. Запись каждого 320-го семпла в новый байтовый массив

Однако, когда я играю в новый wav, это неразличимый шум. Вот мой код:

const sourceRate:uint = 8000;
const targetRate:uint = 11025;
var lcm:uint = lcm(targetRate, sourceRate); // = 3528000
var l:uint = lcm / sourceRate; // = 441
var m:uint = lcm / targetRate; // = 320

// upsample by factor of l
var upsampleData:ByteArray = new ByteArray();
upsampleData.endian = Endian.LITTLE_ENDIAN;

// originalWavData is a ByteArray of the source wav data
// fill is a ByteArray that contains 440 zeroes, written using writeShort(0x0)

while(originalWavData.bytesAvailable > 1) {
    upsampleData.writeBytes(fill);
    upsampleData.writeShort(originalWavData.readShort());
}

// downsample by factor of m
var downsampleData:ByteArray = new ByteArray();
downsampleData.endian = Endian.LITTLE_ENDIAN;

upsampleData.position = 0;

for(var k:uint=0; k<upsampleData.length; k++) {
    upsampleData.position = k * m;
    if(upsampleData.bytesAvailable < 2) break;
    downsampleData.writeShort(upsampleData.readShort());
}

Может кто-нибудь показать мне, что я делаю неправильно в своем коде? Это мой первый пост с вопросом, поэтому, если я что-то забыл или мне нужно предоставить дополнительную информацию, сообщите мне.

Спасибо!

Обновление:

Я не нашел ответа Арика и теперь успешно повышаю его, используя следующий код:

/**
 * Generates a ByteArray containing numSamples of
 * data using linear interpolation between points
 * y0 and y1.
 */
function interpolate(y0:int, y1:int, numSamples:uint):ByteArray {
    var b:ByteArray = new ByteArray();
    b.endian = Endian.LITTLE_ENDIAN;
    var m:Number = Math.round((y1-y0)/numSamples);
    for(var i:uint=0; i<numSamples; i++) {
        var n:int = m * i + y0;
        b.writeShort(n);
    }
    b.position = 0;
    return 0;
}

// upsample by factor of l
var n1:int = 0;
while(originalWavData.bytesAvailable > 1) {
    var sample:int = originalWavData.readShort();
    upsampleData.writeBytes(interpolate(n1, sample, (l-1)));
    n1 = sample;
}

// downsample by factor of m
while(upsampleData.bytesAvailable > 1) {
    downsampleData.writeShort(upsampleData.readShort());
    upsampleData.position += ((m-1)*2);
}

Несколько моментов, которые следует отметить в этом решении: я повышаю частоту аудио-капчи, поэтому качество звука не так уж важно. Кроме того, первые сэмплы - просто тишина, поэтому мне не нужно было вычислять значение слева от первого сэмпла. Вот почему n1 изначально равно 0. Кроме того, вместо усреднения сгенерированных сэмплов в моем даунсэмпле я просто брал каждый M-й сэмпл, и для моих целей это звучало просто отлично.

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

1 Ответ

5 голосов
/ 17 декабря 2009

Есть ли конкретная причина, по которой вы хотите увеличить выборку? Повышение частоты дискретизации не даст вам более качественного звука, равно как и запись разговора по мобильному телефону на компакт-диск даст вам звук «CD-качества».

Если вы действительно хотите повысить частоту, то, как упоминал Лассе, не просто вставляйте нули. Как указывает Википедия, вам нужно интерполировать то, какими были бы сэмплы, увеличив частоту до 3528000 Гц, а затем уменьшив частоту до 11025 Гц.

Для повышения дискретизации один из способов сделать это - использовать линейный алгоритм между каждой точкой. Скажем, первые три сэмпла в записи 8 кГц: [15, 25, 33].

Чтобы повысить частоту этих трех сэмплов до 3528000 Гц, вам необходимо вывести (441 * 3 = 1323) сэмплов. 220-й образец должен быть 15, 661-й должен быть 25, а 1102-й образец должен быть 33. Проведите прямую линию между точками, и вы получите приличный результат.

После того, как вы это сделаете, вам нужно сэмплировать 1323 сэмпла примерно до 4 сэмплов. Первый должен быть средним для выборок 160-480, второй - для 481-800, третий - для 801-1160, а четвертый - для 1161-1480. Конечно, вам не хватает сэмплов 1324-1480, которые вы могли бы сгенерировать с помощью сэмпла №4 в исходных данных.

Это должно, по крайней мере, приблизить вас. Но прежде чем сделать это, спросите себя, действительно ли вам нужно повышать семпл. Если вы не используете какое-то странное программное обеспечение, которое принимает только определенные форматы, вам лучше просто предоставить ему имеющиеся у вас данные.

...