У меня есть приложение Mac .net, и все, что ему нужно сделать, это записать звук, а затем записать его в файл WAV.
Я использую оболочку C# для PortAudio для записи звука. Мне удалось успешно записать и записать файл WAV для одноканального звука и то же самое для двухканального. Но когда я пытаюсь записать двухканальный звук, а затем записать его как одноканальный, он искажается. Объединение 2 каналов в 1 осуществляется путем взятия чередующихся пар выборок, их сложения и последующего деления на 2. При этом предпринимаются шаги, чтобы избежать переполнения.
И все же при объединении каналов, конечный результат искажается. Я убежден, что это что-то элементарное и простое, что я делаю ужасно неправильно, но больше не могу этого заметить.
Код для записи:
Меня не слишком волнует потеря качества звука, главное, чтобы по нему можно было четко и легко понимать человеческую речь.
Пример искаженного звука: https://www.dropbox.com/scl/fi/5204zxtp ... xj8pm&dl=0
Приведенный выше код является конечной точкой после нескольких разных попыток.
В настоящее время частота дискретизации, которую мы записываем в WAV, составляет половину той, которую мы при записи, но без этого изменения длина звука уменьшается вдвое и воспроизводится с двойной скоростью.
Частота дискретизации раньше составляла 16000, и это, казалось, давало немного лучшие результаты, но с все, что я читал в Интернете, похоже, что 44100 - лучший выбор.
Изначально, когда я объединял каналы, он был просто статическим, но преобразование сэмплов в 32-битное форматирование при их объединении, кажется, помогает избегайте переполнения.
Я пробовал разные форматы сэмплов, а также пробовал нечередующийся звук, но, похоже, это не делает ничего лучше или хуже.
Это определенно может хорошо работать, поскольку запись 2-канального звука и запись его в виде 2-канального звука работают хорошо, поэтому я вполне уверен, что это не аппаратная проблема.
Основная причина почему я пытаюсь объединить 2 канала звука в 1, так это то, что мне нужно, чтобы конечный файл WAV был как можно меньше. Мне нужно хорошее качество звука, и то, что я могу сэкономить место, является бонусом, а объединение двух каналов в один приведет к значительному сокращению размера файла.
У меня есть приложение Mac .net, и все, что ему нужно сделать, это записать звук, а затем записать его в файл WAV. Я использую оболочку C# для PortAudio для записи звука. Мне удалось успешно записать и записать файл WAV для одноканального звука и то же самое для двухканального. Но когда я пытаюсь записать двухканальный звук, а затем записать его как одноканальный, он искажается. Объединение 2 каналов в 1 осуществляется путем взятия чередующихся пар выборок, их сложения и последующего деления на 2. При этом предпринимаются шаги, чтобы избежать переполнения. И все же при объединении каналов, конечный результат искажается. Я убежден, что это что-то элементарное и простое, что я делаю ужасно неправильно, но больше не могу этого заметить. Код для записи: [code] private static readonly int _sampleRate = 44100; private static int _totalSamplesWritten = 0; private const ushort BIT_DEPTH = 16 ;
for (var i = 0; i < frameCount; i++) { var sampleL = samples[i]; var overflowSafeSampleL = Convert.ToInt32(sampleL); var sampleR = samples[i + 1]; var overflowSafeSampleR = Convert.ToInt32(sampleR);
var combinedSample = overflowSafeSampleL + overflowSafeSampleR; var dividedSample = Convert.ToInt16(combinedSample / 2);
_outputFileWriter.Write(dividedSample); i++; }
_totalSamplesWritten += (int)frameCount;
return StreamCallbackResult.Continue; }
_stream = new PortAudioSharp.Stream( inParams: param, outParams: null, sampleRate: _sampleRate, framesPerBuffer: 256, streamFlags: StreamFlags.ClipOff, callback: param.channelCount > 1 ? CallbackStereoInput : CallbackMonoInput, userData: IntPtr.Zero ); [/code] Код для записи заголовка WAV: [code]WriteWavHeader(_outputFileWriter, 1, BIT_DEPTH, _sampleRate / 2, _totalSamplesWritten);
private static void WriteWavHeader(BinaryWriter writer, ushort channelCount, ushort bitDepth, int sampleRate, int totalSampleCount) { writer.Seek(0, SeekOrigin.Begin); writer.Write(Encoding.ASCII.GetBytes("RIFF")); writer.Write((bitDepth / 8 * totalSampleCount) + 36); writer.Write(Encoding.ASCII.GetBytes("WAVE")); writer.Write(Encoding.ASCII.GetBytes("fmt ")); writer.Write(16); writer.Write((ushort)1); writer.Write(channelCount); writer.Write(sampleRate); writer.Write(sampleRate * channelCount * bitDepth / 8); writer.Write((ushort)(channelCount * bitDepth / 8)); writer.Write(bitDepth); writer.Write(Encoding.ASCII.GetBytes("data")); writer.Write(bitDepth / 8 * totalSampleCount); } [/code] Меня не слишком волнует потеря качества звука, главное, чтобы по нему можно было четко и легко понимать человеческую речь. Пример искаженного звука: https://www.dropbox.com/scl/fi/5204zxtpjkqa4ewxhph0j/Audio.wav?rlkey=9urdo4s0zqtyd3hxi1oscko9b&st=w02xj8pm&dl=0 Приведенный выше код является конечной точкой после нескольких разных попыток. [list] [*]В настоящее время частота дискретизации, которую мы записываем в WAV, составляет половину той, которую мы при записи, но без этого изменения длина звука уменьшается вдвое и воспроизводится с двойной скоростью. [*]Частота дискретизации раньше составляла 16000, и это, казалось, давало немного лучшие результаты, но с все, что я читал в Интернете, похоже, что 44100 - лучший выбор. [*]Изначально, когда я объединял каналы, он был просто статическим, но преобразование сэмплов в 32-битное форматирование при их объединении, кажется, помогает избегайте переполнения. [*]Я пробовал разные форматы сэмплов, а также пробовал нечередующийся звук, но, похоже, это не делает ничего лучше или хуже. [*]Это определенно может хорошо работать, поскольку запись 2-канального звука и запись его в виде 2-канального звука работают хорошо, поэтому я вполне уверен, что это не аппаратная проблема. [*]Основная причина почему я пытаюсь объединить 2 канала звука в 1, так это то, что мне нужно, чтобы конечный файл WAV был как можно меньше. Мне нужно хорошее качество звука, и то, что я могу сэкономить место, является бонусом, а объединение двух каналов в один приведет к значительному сокращению размера файла. [/list]