Как избежать искажений звука при объединении 2 каналов в 1C#

Место общения программистов C#
Ответить
Anonymous
 Как избежать искажений звука при объединении 2 каналов в 1

Сообщение Anonymous »

У меня есть приложение .net для Mac, и все, что ему нужно сделать, это записать звук, а затем записать его в файл WAV.
Я использую оболочку C# для PortAudio для записи звука. Мне удалось успешно записать и записать WAV-файл для 1-канального звука, то же самое для 2-канального. Но когда я пытаюсь записать 2-канальный звук, а затем записать его как 1-канальный звук, он искажается. Комбинация двух каналов с одним осуществляется путем взятия чередующихся пар выборок, их сложения и последующего деления на 2. При этом предпринимаются шаги, чтобы избежать переполнения.
И все же при объединении каналов, конечный результат искажается. Я убежден, что это что-то элементарное и простое, что я делаю ужасно неправильно, но больше не могу этого заметить.
Код для записи:

Код: Выделить всё

private static readonly int _sampleRate = 44100;
private static int _totalSamplesWritten = 0;
private const ushort BIT_DEPTH = 16 ;

var param = new StreamParameters
{
device = _indexOfDevice,
channelCount = device.maxInputChannels > 1 ? 2 : 1,
sampleFormat = SampleFormat.Int16,
suggestedLatency = device.defaultLowInputLatency,
hostApiSpecificStreamInfo = IntPtr.Zero
};

StreamCallbackResult CallbackStereoInput(
IntPtr input,
IntPtr output,
uint frameCount,
ref StreamCallbackTimeInfo timeInfo,
StreamCallbackFlags statusFlags,
IntPtr userData
)
{
var samples = new short[frameCount];
Marshal.Copy(input, samples, 0, (int)frameCount);

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
);
Код для записи заголовка WAV:

Код: Выделить всё

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);
}
Меня не слишком волнует потеря качества звука, главное, чтобы по нему можно было четко и легко понимать человеческую речь.
Пример искаженного звука:
https://www.dropbox.com/scl/fi/5204zxtp ... xj8pm&dl=0
Приведенный выше код является конечной точкой после нескольких разных попыток.
  • В настоящее время частота дискретизации, которую мы записываем в WAV, составляет половину частоты, которую мы записываем. at, но без этого изменения длина звука уменьшается вдвое и воспроизводится с двойной скоростью.
  • Частота дискретизации раньше была 16000, и это, казалось, давало немного лучшие результаты, но, судя по всему, я Вы читали в Интернете, кажется, что 44100 — лучший выбор?
  • Изначально, когда я объединял каналы, он был просто статическим, но приведение сэмплов к 32-битному формату при объединении, кажется, помогает избежать переполнения.
  • Я пробовал разные форматы сэмплов, пробовал нечередующийся звук, но, похоже, это не делает ничего лучше или хуже.
  • Он определенно может хорошо работать при записи 2-канального звука и записи его в качестве 2-канального звука, поэтому я вполне уверен, что это не аппаратная проблема.
  • Основная причина, по которой я пытаюсь это сделать. объединить 2 канала звука в 1, мне нужно, чтобы конечный файл WAV был как можно меньше. Мне нужно хорошее качество звука, и то, что я могу сэкономить место, является бонусом, а объединение двух каналов в один приведет к значительному сокращению размера файла.


Подробнее здесь: https://stackoverflow.com/questions/791 ... els-into-1
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»