Здесь есть две задачи, которые вы пытаетесь выполнить:
- Объединение нескольких звуковых файлов в один звуковой файл
- Сохранение полученного файла в формате MP3.
Насколько я обнаружил, с пунктом 2 у вас возникнет немало проблем. На сегодняшний день я не нашел чистого MP3-кодера .Net.Все те, которые я нахожу, полагаются на P / Вызывает нативный код (который, конечно, не будет работать на телефоне).
Что касается объединения файлов, вы не хотите рассматривать их как SoundEffectInstance.Этот класс предназначен только для воспроизведения, и он абстрагирует большинство деталей звукового файла.Вместо этого вам нужно будет рассматривать звуковые файлы как массивы целых.Я предполагаю, что частота дискретизации всех трех звуковых файлов одинакова и это 16-битные записи.Я также собираюсь предположить, что эти волновые файлы записаны в моно.Сейчас я придерживаюсь простого сценария.Вы можете расширить его с помощью стерео и различных частот дискретизации после того, как освоите этот более простой сценарий.
Первые 48 байтов волновых файлов - это не что иное, как заголовок.Пропустите это (пока) и прочитайте содержимое волновых файлов в их собственные массивы.Как только они все прочитают, мы можем начать смешивать их вместе.Игнорируя разницу во времени, в которой вы хотите начать воспроизводить эти звуки, если мы хотим начать производство сэмпла, который является объединенным результатом всех трех, мы могли бы сделать это, сложив значения в массиве звуковых файлов вместе и записав это в массивдержать наш результат.Но есть проблема.16-битные числа могут доходить только до 32 767 (и до -32 768).Если объединенное значение всех трех звуков выйдет за эти пределы, вы получите действительно плохое искажение.Самый простой (хотя и не обязательно лучший) способ справиться с этим - рассмотреть максимальное количество одновременно воспроизводимых звуков и соответственно уменьшить их значения.От 3,5 секунд до 4 секунд у вас будут воспроизводиться все три звука.Таким образом, мы будем масштабировать путем деления на три.Другой способ - суммировать образцы звука, используя тип данных, который может выйти за пределы этого диапазона, а затем нормализовать значения обратно в этот диапазон, когда вы закончите смешивать их вместе.
Давайте определим некоторые параметры.
int SamplesPerSecond = 22000;
int ResultRecordingLength = 7;
short[] Sound01;
short[] Sound02;
short[] Sound03;
int[] ResultantSoundBuffer;
short[] ProcessedResultSoundBuffer;
//Insert code to populate sound array's here.
// Sound01.Length will equal 5.0*SamplesPerSecond
// Sound02.Length will equal 1.0*SamplesPerSecond
// Sound03.Length will equal 3.5*SamplesPerSecond
ResultantSound = new int[ResultRecordingLength*SamplesPerSecond];
После прочтения звуковых файлов и подготовки массива для получения полученного файла вы можете начать рендеринг.Есть несколько способов сделать это.Вот один из них:
void InitResultArray(int[] resultArray)
{
for(int i=0;i<resultArray.Length;++i)
{
resultArray[i]=0;
}
}
void RenderSound(short[] sourceSound, int[] resultArray, double timeOffset)
{
int startIndex = (int)(timeOffset*SamplesPerSecond);
int readIndex = 0;
for(int readIndex=0;((readIndex<sourceSound.Length)&&(readIndex+sourceSound<resultArray.Length;++readIndex)
{
resultArray[readIndex+startIndex] += (int)sourceSound[readIndex];
}
}
RangeAdjust(int[] resultArray)
{
int max = int.MinimumValue;
int min = int.MaximumValue;
for(int i=0;i<resultArray;++i)
{
max = Math.Max(max, resultArray[i]);
min = Math.Min(min, resultArray[i]);
}
//I want the range normalized to [-32,768..32,768]
//you may want to normalize differently.
double scale = 65536d/(double)(max-min);
double offset = 32767-(max*scale);
for(int i=0;i<resultArray.Length;++i)
{
resultArray[i]= (scale*resultArray[i])+offset;
}
}
Вы бы вызвали InitResultAttay, чтобы убедиться, что массив результатов заполнен нулями (я считаю, что это по умолчанию, но я все же предпочитаю явно устанавливать его в ноль), а затем вызвать RenderSound () для каждого звука, который вы хотите в вашем результате.После того, как вы воспроизвели ваши звуки, позвоните в RangeAdjust, чтобы нормализовать звук.Осталось только записать его в файл.Вам нужно будет конвертировать из целых обратно в шорты.
short[] writeBuffer = new short[ResultantSound.Length];
for(int i=0;i<writeBuffer.Length;++i)
writeBuffer[i]=(short)ResultantSound[i];
Теперь смешанный звук готов для записи в файл.Отсутствует только одна вещь, вам нужно написать 48-байтовый заголовок волны перед записью файла.Я написал код о том, как это сделать здесь: http://www.codeproject.com/KB/windows-phone-7/WpVoiceMemo.aspx