15

C# を学習する言い訳として、オーディオ ファイルの作成という単純なプロジェクトのコーディングを試みています。まず、WAVE フォーマットを満たすファイルを書き込めるようにしたいと思います。形式をオンラインで調べましたが (たとえば、こちら)、ファイルを再生しようとすると、正しく開かれません。これが私のコードです。何かが欠けているか間違っていますか?

uint numsamples = 44100;
ushort numchannels = 1;
ushort samplelength = 1; // in bytes
uint samplerate = 22050;

FileStream f = new FileStream("a.wav", FileMode.Create);
BinaryWriter wr = new BinaryWriter(f);

wr.Write("RIFF");
wr.Write(36 + numsamples * numchannels * samplelength);
wr.Write("WAVEfmt ");
wr.Write(16);
wr.Write((ushort)1);
wr.Write(numchannels);
wr.Write(samplerate);
wr.Write(samplerate * samplelength * numchannels);
wr.Write(samplelength * numchannels);
wr.Write((ushort)(8 * samplelength));
wr.Write("data");
wr.Write(numsamples * samplelength);

// for now, just a square wave
Waveform a = new Waveform(440, 50);

double t = 0.0;
for (int i = 0; i < numsamples; i++, t += 1.0 / samplerate)
{
    wr.Write((byte)((a.sample(t) + (samplelength == 1 ? 128 : 0)) & 0xff));
}
4

4 に答える 4

13

主な問題は次のとおりです。

BinaryWriter.Write(string)読み戻すための長さのプレフィックスが付いた文字列を書き込みます。BinaryReaderあなたの場合のように使用することを意図したものではありません。を使用する代わりに、バイトを直接書き込む必要がありますBinaryWriter.Write(string)

あなたがすべきこと:

文字列をバイトに変換してから、バイトを直接書き込みます。

byte[] data = System.Text.Encoding.ASCII.GetBytes("RIFF");
binaryWriter.Write(data);

または1行にします。

binaryWriter.Write(System.Text.Encoding.ASCII.GetBytes("RIFF"));

書いている整数が必要なサイズと同じでない可能性があるなど、他の問題もある可能性があります。それらを注意深くチェックする必要があります。

エンディアンに関しては、データがリトルエンディアンであり、リトルエンディアンを使用していることを示すリンクがあるBinaryWriterため、これは問題にはなりません。

于 2013-02-02T08:44:10.920 に答える
4

可能な限り最も簡単な方法は、次のように変更するだけです。

wr.Write("RIFF");

に:

wr.Write("RIFF".ToArray());

バイナリ ファイルに文字列を書き込むと、後で文字列に逆シリアル化できるように、文字列の長さが含まれます。この場合、4 バイトを 4 バイトとして書き込む必要があり、それを char 配列に変換すると、それが実現します。

于 2015-04-07T17:37:56.917 に答える
3

適切な WAV データがありませんが、ヘッダーを生成するコードの部分を次のコードに置き換えてみてください (適切に置き換えてください)。

wr.Write(Encoding.ASCII.GetBytes("RIFF"));
wr.Write(0);
wr.Write(Encoding.ASCII.GetBytes("WAVE"));
wr.Write(Encoding.ASCII.GetBytes("fmt "));
wr.Write(18 + (int)(numsamples * samplelength));
wr.Write((short)1); // Encoding
wr.Write((short)numchannels); // Channels
wr.Write((int)(samplerate)); // Sample rate
wr.Write((int)(samplerate * samplelength * numchannels)); // Average bytes per second
wr.Write((short)(samplelength * numchannels)); // block align
wr.Write((short)(8 * samplelength)); // bits per sample
wr.Write((short)(numsamples * samplelength)); // Extra size
wr.Write("data");
于 2013-02-02T08:31:35.717 に答える