2017-12-05 24 views
0

WAVファイルをC#のバッファ配列に読み込もうとしていますが、いくつか問題があります。私はオーディオファイルを管理するファイルストリームを使用しています。ここに私が持っているものは...C#の配列にオーディオファイルを読み込む方法

FileStream WAVFile = new FileStream(@"test.wav", FileMode.Open); 

     //Buffer for the wave file... 
     BinaryReader WAVreader = new BinaryReader(WAVFile); 

     //Read information from the header. 
     chunkID = WAVreader.ReadInt32(); 
     chunkSize = WAVreader.ReadInt32(); 
     RiffFormat = WAVreader.ReadInt32(); 

     ... 

     channels = WAVreader.ReadInt16(); 
     samplerate = WAVreader.ReadInt32(); 
     byteRate = WAVreader.ReadInt32(); 
     blockAllign = WAVreader.ReadInt16(); 
     bitsPerSample = WAVreader.ReadInt16(); 

     dataID = WAVreader.ReadInt32(); 
     dataSize = WAVreader.ReadInt32(); 

上記は、WAVファイルのヘッダーからのデータの読み取りです。それでは、私はこれを持っています:

musicalData = WAVreader.ReadBytes(dataSize); 

...実際のサンプルデータを読むには、これはオーディオの60秒間は26バイトです。これは正しいです?

byte []配列をdouble []に​​変換するにはどうすればよいですか?

+0

26バイトのサイズがわかるとすぐに間違っているはずです。 – Steve

+0

dataIDの値を確認してください。それは文字 "fmt"を含むべきです。私はそれが32ビットのintとして読まれるときに逆転されると思います。つまり、次のものを含みます:0x20 0x74 0x6d 0x66。これは、正しい場所からdataSize値を読み取っているかどうかを判断するのに役立ちます。 – Olan

答えて

0

私はWAVEファイルの処理に触れてから10〜15年経ちましたが、ほとんどの人が単純な固定サイズのヘッダーとしてPCMでエンコードされたオーディオデータを取得するという最初の印象とは異なり、WAVEファイルはもう少しです複雑なRIFF形式のファイル。

RIFFファイルの処理やさまざまなケースを再エンジニアリングする代わりに、interopを使用してRIFFファイル形式を処理するAPIを呼び出すことをお勧めします。

this exampleにデータバッファ(およびどのバッファがあるかに関するメタ情報)を開いて取得する方法の例を見ることができます。これはC++で書かれていますが、適切なオーディオバッファを手に入れるためには、mmioOpenmmioReadmmioDescendmmioAscendのAPIを使用する必要があります。

0

このコードはこのトリックを行う必要があります。これは、waveファイルを正規化されたdouble配列(-1対1)に変換しますが、代わりにint/short配列にするのは簡単です(/32768.0ビットを削除し、代わりに32768を追加してください)。読み込まれたwavファイルがモノラルであると判明した場合、right []配列はnullに設定されます。

65536サンプル配列を作成し、-1から1までのウェーブを作成した後で、サンプルがどれも通過しないように見えることはありません天井や床。あなたは、あなたのWAVファイルを想定して、プラグインを使用したい場合は

// convert two bytes to one double in the range -1 to 1 
static double bytesToDouble(byte firstByte, byte secondByte) 
{ 
    // convert two bytes to one short (little endian) 
    short s = (secondByte << 8) | firstByte; 

    // convert to range from -1 to (just below) 1 
    return s/32768.0; 
} 

// Returns left and right double arrays. 'right' will be null if sound is mono. 
public void openWav(string filename, out double[] left, out double[] right) 
{ 
    byte[] wav = File.ReadAllBytes(filename); 

    // Determine if mono or stereo 
    int channels = wav[22];  // Forget byte 23 as 99.999% of WAVs are 1 or 2 channels 

    // Get past all the other sub chunks to get to the data subchunk: 
    int pos = 12; // First Subchunk ID from 12 to 16 

    // Keep iterating until we find the data chunk (i.e. 64 61 74 61 ...... (i.e. 100 97 116 97 in decimal)) 
    while(!(wav[pos]==100 && wav[pos+1]==97 && wav[pos+2]==116 && wav[pos+3]==97)) 
    { 
     pos += 4; 
     int chunkSize = wav[pos] + wav[pos + 1] * 256 + wav[pos + 2] * 65536 + wav[pos + 3] * 16777216; 
     pos += 4 + chunkSize; 
    } 

    pos += 8; 

    // Pos is now positioned to start of actual sound data. 
    int samples = (wav.Length - pos)/2;  // 2 bytes per sample (16 bit sound mono) 

    if (channels == 2) 
    { 
     samples /= 2;  // 4 bytes per sample (16 bit stereo) 
    } 

    // Allocate memory (right will be null if only mono sound) 
    left = new double[samples]; 

    if (channels == 2) 
    { 
     right = new double[samples]; 
    } 
    else 
    { 
     right = null; 
    } 

    // Write to double array/s: 
    int i=0; 
    while (pos < length) 
    { 
     left[i] = bytesToDouble(wav[pos], wav[pos + 1]); 
     pos += 2; 

     if (channels == 2) 
     { 
      right[i] = bytesToDouble(wav[pos], wav[pos + 1]); 
      pos += 2; 
     } 

     i++; 
    } 
} 

は(最も一般的である)16ビットPCM、あなたはバイト配列にそれを読み出すためにNAudioを使用し、その後にそのコピーすることができますが含まれています便宜上16ビット整数の配列ステレオの場合、サンプルは左右にインターリーブされます。

using (WaveFileReader reader = new WaveFileReader("myfile.wav")) 
{ 
    Assert.AreEqual(16, reader.WaveFormat.BitsPerSample, "Only works with 16 bit audio"); 
    byte[] buffer = new byte[reader.Length]; 
    int read = reader.Read(buffer, 0, buffer.Length); 
    short[] sampleBuffer = new short[read/2]; 
    Buffer.BlockCopy(buffer, 0, sampleBuffer, 0, read); 
} 

個人的に私ができる限り第三者のライブラリを使用しないようにしてください。しかし、コードをより使いやすく見えるようにするには、このオプションがまだあります。

+0

私が26バイトを返す理由を知っていますか?それはオーディオの30秒間は正しく見えません – Bluehand

関連する問題