Частота дискретизации микрофона по умолчанию в FlashPlayer составляет 8 кГц моно, или, если она недоступна, первая из доступных: 11,025 кГц, 22,05 кГц или 44,1 кГц. Аудио выход всегда 44,1 кГц стерео. Это означает, что образцов, которые вы получаете, слишком мало: 44,1 / 8 ~ = 5,5.
Это можно исправить, установив частоту дискретизации записи на 44,1 кГц:
microphone.rate = 44; // Yes, the API doesn't want the decimals
Вы также можете оставить курс, например, на 22 или 11, а затем записать дополнительные дубликаты сэмплов в буфер (простая «повышающая дискретизация») при записи - то есть записать 4 числа с плавающей запятой, а не 2, если запись на 22 кГц, 8, если запись на 11 кГц.
Еще одна вещь, о которой следует помнить, это то, что выходной сэмпл - это не одно с плавающей точкой, а два - по одному на каждый канал. Таким образом, микрофон выдаст вам 8192 моносэмпла, которые вы - как и должны - применить к обоим каналам, записав каждый семпл дважды. Теперь у вас есть 8192 "стерео" семпла.
Однако, когда вы пишете вывод, вы пишете не более 8192 с плавающей точкой (i
) - что соответствует 4096 стерео сэмплам. Другая половина - я полагаю из вашего кода и ваших результатов - выброшена.
В итоге получается первая половина из 8192 сэмплов, записанных с частотой дискретизации, примерно в 5,5 раз меньшей, чем частота сэмплирования воспроизведения. Это означает, что звук будет воспроизводиться в 2 * 5,5 = 11 раз быстрее.
Обязательно запишите все сэмплы на выход и запишите их с частотой 44,1 кГц (или с повышением частоты, как описано выше), и он должен воспроизводиться с правильной скоростью.
В sidenote, event.data.writeBytes
, вероятно, будет много быстрее для копирования буфера (предположительно - на самом деле не проверял):
_lastRecord = new ByteArray();
_lastRecord.writeBytes(_buffer, 0, _buffer.bytesAvailable);
То же самое для записи данных примера:
public function handlePlaybackSampleData(p_sampleEvent:SampleDataEvent) :void
{
// Maximum amount of samples we're allowed to write: 8192
// Copying bytes here, rather than floats, so:
// 8192 samples * 2 channels * 4 bytes per float = 65536:
var bytesToCopy:int = Math.min(_lastRecord.bytesAvailable, 65536);
// Using _lastRecord.position since some of it may have been written on the
// last call to handlePlaybackSampleData if it had more than 8192 samples:
p_sampleEvent.data.writeBytes(
_lastRecord,
_lastRecord.position,
bytesToCopy
);
}