Как мне увеличить время работы аудиосинтезатора?

#c# #audio

#c# #Аудио

Вопрос:

Я создал аудиосинтезатор, используя информацию, найденную на http://soundfile.sapp.org/doc/WaveFormat /.

 private const int SAMPLE_RATE = 44100;
private const short BITS_PER_SAMPLE = 16;
short[] asSoundValues = new short[SAMPLE_RATE]
float fFreq = 440;

for (int iValueCount = 0; iValueCount < SAMPLE_RATE; iValueCount  ) 
{
  asSoundValues[iValueCount] = Convert.ToInt16(short.MaxValue *
    Math.Sin(((Math.PI * 2 * fFreq) / SAMPLE_RATE) * iValueCount));
}

byte[] abBinarySoundValues = new byte[SAMPLE_RATE * sizeof(short)];
Buffer.BlockCopy(asSoundValues, 0, abBinarySoundValues, 0,
                   asSoundValues.Length * sizeof(short));
using (MemoryStream msMemoryStream = new MemoryStream()) 
{
  using (BinaryWriter bwBinaryWriter = new BinaryWriter(msMemoryStream)) 
  {
    short sBlockAlign = BITS_PER_SAMPLE / 8;
    int iSubChunkTwoSize = SAMPLE_RATE * sBlockAlign;
    bwBinaryWriter.Write(new[] { 'R', 'I', 'F', 'F' });
    bwBinaryWriter.Write(36   iSubChunkTwoSize);
    bwBinaryWriter.Write(new[] { 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ' });
    bwBinaryWriter.Write(16);
    bwBinaryWriter.Write((short)1);
    bwBinaryWriter.Write((short)1);
    bwBinaryWriter.Write(SAMPLE_RATE);
    bwBinaryWriter.Write(SAMPLE_RATE * sBlockAlign);
    bwBinaryWriter.Write(sBlockAlign);
    bwBinaryWriter.Write(BITS_PER_SAMPLE);
    bwBinaryWriter.Write(new[] { 'd', 'a', 't', 'a' });
    bwBinaryWriter.Write(iSubChunkTwoSize);
    bwBinaryWriter.Write(abBinarySoundValues);
    msMemoryStream.Position = 0;
    new SoundPlayer(msMemoryStream).Play();
  }
}
  

Звук длится 1 секунду. Как мне продлить этот звук, чтобы он длился дольше — например, 5 секунд?

Комментарии:

1. short[] asSoundValues = new short[SAMPLE_RATE * numberOfSeconds] ?

2. Пробовал — длина по-прежнему составляет 1 секунду.

Ответ №1:

В соответствии с форматом wave, это то, Subchunk2Size что в конечном итоге определяет длину WAV, что помогло мне выяснить все, что нужно было бы изменить, кроме ваших массивов сэмплов. Итак, это все изменения, которые вам нужно будет внести:

 for (int iValueCount = 0; iValueCount < SAMPLE_RATE * numberOfSeconds; iValueCount  ) 
short[] asSoundValues = new short[SAMPLE_RATE * numberOfSeconds]
byte[] abBinarySoundValues = new byte[SAMPLE_RATE * sizeof(short) * numberOfSeconds];
int iSubChunkTwoSize = SAMPLE_RATE * sBlockAlign * numberOfSeconds;
  

Комментарии:

1. Это близко! 2-секундный пример: первая половина abBinarySoundValues должна быть заполнена значениями asSoundValues — вторая половина также должна быть заполнена значениями asSoundValues .

2. @ttom Я обновил свой ответ; ваш цикл for также нуждался в изменении.

Ответ №2:

Это работает (если я не сделал никаких опечаток):

 private const int SAMPLE_RATE = 44100;
private const short BITS_PER_SAMPLE = 16;
short[] asSoundValues = new short[SAMPLE_RATE]
float fFreq = 440;
int iLengthOfTimeInSecs = 5;

for (int iValueCount = 0; iValueCount < SAMPLE_RATE; iValueCount  ) 
{
  asSoundValues[iValueCount] = Convert.ToInt16(short.MaxValue *
    Math.Sin(((Math.PI * 2 * fFreq) / SAMPLE_RATE) * iValueCount));
}

int iNumOfShortsIn_asSoundValuesArray = SAMPLE_RATE;
int iNumOfBytesIn_asSoundValuesArray = SAMPLE_RATE * sizeof(short);
int iNumOfBytesIn_abBinarySoundValuesArray = iNumOfBytesIn_asSoundValuesArray *
                                               iLengthOfTimeInSecs;
byte[] abBinarySoundValues = new byte[iNumOfBytesIn_abBinarySoundValuesArray];
for (int ii = 0; ii < iLengthOfTimeInSecs; ii  ) 
{
  Buffer.BlockCopy(asSoundValues, 
                    0, 
                    abBinarySoundValues, 
                    iNumOfBytesIn_asSoundValuesArray * ii,
                    iNumOfBytesIn_asSoundValuesArray);
}
using (MemoryStream msMemoryStream = new MemoryStream()) 
{
  using (BinaryWriter bwBinaryWriter = new BinaryWriter(msMemoryStream)) 
  {      
    short sBlockAlign = BITS_PER_SAMPLE / 8;
    int iSubChunkTwoSize = iNumOfShortsIn_asSoundValuesArray * 
                             sBlockAlign * iLengthOfTimeInSecs;
    bwBinaryWriter.Write(new[] { 'R', 'I', 'F', 'F' });
    bwBinaryWriter.Write(36   iSubChunkTwoSize);
    bwBinaryWriter.Write(new[] { 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ' });
    bwBinaryWriter.Write(16);
    bwBinaryWriter.Write((short)1);
    bwBinaryWriter.Write((short)1);
    bwBinaryWriter.Write(iNumOfShortsIn_asSoundValuesArray);
    bwBinaryWriter.Write(iNumOfShortsIn_asSoundValuesArray * sBlockAlign);
    bwBinaryWriter.Write(sBlockAlign);
    bwBinaryWriter.Write(BITS_PER_SAMPLE);
    bwBinaryWriter.Write(new[] { 'd', 'a', 't', 'a' });
    bwBinaryWriter.Write(iSubChunkTwoSize);
    bwBinaryWriter.Write(abBinarySoundValues);
    msMemoryStream.Position = 0;
    new SoundPlayer(msMemoryStream).Play();
  }
}