Мне нужна возможность объединить два или более WAV файла вместе в один .wav файл. Я должен делать это программно, используя С# (сторонние продукты не являются опцией). Я знаю класс System.Media.SoundPlayer, но я не хочу играть в WAV, но только для его создания.
Как объединить 2 или более файлов .WAV вместе программно?
Ответ 1
Вот базовая функция конкатенации WAV, построенная с помощью NAudio. Это гарантирует, что только фрагменты данных объединены (в отличие от примера кода в этой статье CodeProject, связанной в другом ответе). Он также защитит вас от конкатенации файлов WAV, которые не имеют одинакового формата.
public static void Concatenate(string outputFile, IEnumerable<string> sourceFiles)
{
byte[] buffer = new byte[1024];
WaveFileWriter waveFileWriter = null;
try
{
foreach (string sourceFile in sourceFiles)
{
using (WaveFileReader reader = new WaveFileReader(sourceFile))
{
if (waveFileWriter == null)
{
// first time in create new Writer
waveFileWriter = new WaveFileWriter(outputFile, reader.WaveFormat);
}
else
{
if (!reader.WaveFormat.Equals(waveFileWriter.WaveFormat))
{
throw new InvalidOperationException("Can't concatenate WAV Files that don't share the same format");
}
}
int read;
while ((read = reader.Read(buffer, 0, buffer.Length)) > 0)
{
waveFileWriter.WriteData(buffer, 0, read);
}
}
}
}
finally
{
if (waveFileWriter != null)
{
waveFileWriter.Dispose();
}
}
}
Ответ 2
Проверьте этот пример кода, кажется, именно то, что вам нужно, с хорошим объяснением, как это сделать:
Конкатенация волновых файлов с использованием С# 2005
Похоже, что он включает в себя извлечение и объединение звуковых данных из всех wav файлов в один фрагмент данных с новым заголовком файла сверху
EDIT: У меня нет опыта использования этого, и я не эксперт. Я просто наткнулся на эту статью и подумал, что это может быть полезно. См. Ответ Марка Хит для лучшего решения
Ответ 3
Один комментарий к ответу Марка:
Оператор ==, похоже, не работает для меня при сравнении волновых форматов. Это безопаснее:
if (!reader.WaveFormat.Equals(waveFileWriter.WaveFormat))
В качестве альтернативы вы можете обернуть читателя в WaveFormatConversionStream и полностью избавиться от проверки формата (не уверен, что он будет работать во всех сценариях, но я смог успешно протестировать его).
Ответ 4
Использование Как присоединиться к файлам .Wav вместе
private void JoinWav()
{
string[] files = new string[] { "1990764-ENG-CONSEC-RESPONSE7.WAV","1990764-ND_A.WAV", "1990764-SIGHT-SP.WAV",
"1990764-SP-CONSEC-RESPONSE6.WAV","1990764-VOCABWORD-004-12-SP.WAV","bi-consec-1-successful.wav",
"bi-transition-instruct.wav","nd_B.wav","sightreceived_B.wav","teststamp_A.wav" };
AudioCompressionManager.Join("res.wav", files);
}
Ответ 5
Если вам нужно получить только байтовый массив, чтобы вставить в базу данных или кто-то еще. Вы можете использовать поток памяти:
public static byte[] Concatenate(IEnumerable<byte[]> sourceData)
{
var buffer = new byte[1024 * 4];
WaveFileWriter waveFileWriter = null;
using (var output = new MemoryStream())
{
try
{
foreach (var binaryData in sourceData)
{
using (var audioStream = new MemoryStream(binaryData))
{
using (WaveFileReader reader = new WaveFileReader(audioStream))
{
if (waveFileWriter == null)
waveFileWriter = new WaveFileWriter(output, reader.WaveFormat);
else
AssertWaveFormat(reader, waveFileWriter);
WaveStreamWrite(reader, waveFileWriter, buffer);
}
}
}
waveFileWriter.Flush();
return output.ToArray();
}
finally
{
waveFileWriter?.Dispose();
}
}
}
private static void AssertWaveFormat(WaveFileReader reader, WaveFileWriter writer)
{
if (!reader.WaveFormat.Equals(writer.WaveFormat))
{
throw new InvalidOperationException("Can't concatenate WAV Files that don't share the same format");
}
}
private static void WaveStreamWrite(WaveFileReader reader, WaveFileWriter writer, byte[] buffer)
{
int read;
while ((read = reader.Read(buffer, 0, buffer.Length)) > 0)
{
writer.Write(buffer, 0, read);
}
}