5

小さな実験的な音楽作品として、標準 C で曲をプログラムしようとしています。コードは、Audacity にインポートできる生の PCM ファイルを出力します。現時点ではすべてが期待どおりに動作しますが、現在使用している 8 ビットではなく、各サンプルを 16 ビットとして書き込もうとすると問題が発生します。

書き込まれる時点まで、現在のサンプルは float として計算され、その境界はほぼ符号付き 8 ビット整数の範囲内に保たれます。次に、次のサンプルのプロセスを繰り返す前に、8 ビット整数として書き込まれます。これは正常に機能し、適切に再生されます。この問題は、16 ビットの生の PCM ファイルとして書き込もうとしたときに発生します。fwrite を使用して結果の 16 ビット整数を書き込むと、fwrite を使用して float を 256 倍し、結果を整数にコピーします。これは、インポート時に期待される結果をもたらさず、期待していたものの非常に歪んだバージョンになります。

問題は書き込み段階でのみ発生するため、以下に有効なコードを追加しました。

ワーキング 8 ビット コード:

if (out<-127) {out=-128;} else if (out>126) {out=127;}
putc(out,fo);

16 ビット コードが機能しない:

if (out<-127) {out=-128;} else if (out>126) {out=127;}
pcm=out*256;
fwrite(&pcm,2,1,fo);

明らかな何かが欠けているだけかもしれませんが、何時間もかけて解決しようとしています。前もって感謝します!

4

6 に答える 6

4

コードを見てみないと正確に何が問題なのかわかりませんが、これにより、Audacity で開くことができる素敵な 1 KHz 正弦波 16 ビット PCM が作成されます。

#include <stdio.h>
#include <math.h>

#ifndef M_PI
#define M_PI 3.14159265358
#endif

int main(void)
{
  FILE* f = fopen("sinewave.pcm", "wb");
  double t;
  for (t = 0; t < 1; t += 1./8000) // 8000 is the sample rate in Hz
  {
    double sample = 15000 * sin(2 * M_PI * 1000 * t); // 1000 Hz sine wave
    short s16 = (short)sample;
    unsigned char c;
    c = (unsigned)s16 % 256;
    fwrite(&c, 1, 1, f);
    c = (unsigned)s16 / 256 % 256;
    fwrite(&c, 1, 1, f);
  }
  fclose(f);
  return 0;
}

Audacity で、[ファイル] -> [インポート] -> [生データ] に移動します。

エンコーディング: 符号付き 16 ビット PCM
バイト オーダー: リトルエンディアン
チャネル: 1 チャネル (モノ)
サンプル レート: 8000

輸入。

于 2012-07-17T11:21:13.747 に答える
3

Audacityの波形を見ると、いくつかの手がかりが得られたと思います。

チェックしましたか:

  • エンディアンは正しいですか?
  • たとえば、符号なし整数を使用することになっていないということですか?
  • ファイルを16ビットとして正しくマークしましたか?

PCMに期待されるフォーマットが何であるかはわかりませんが、これらはすべて問題の候補である可能性があります。

于 2010-07-24T15:22:23.943 に答える
0

変換を行うときは、型キャストを行うことをお勧めします。たとえば、outがfloatの場合、

putc((int) out, fo);

数値を整数として書き込みたいことをコンパイラに通知します。

確かに、コンパイラはputcのようなものでそれを理解しますが、これは参照には機能しません。pcm変数をfloatとして宣言すると、fwriteは必要なデータの代わりに浮動小数点データを書き込みます。だから私は同じ質問をします:pcmは整数型ですか?

もう1つの質問は、ここに浮動小数点が本当に必要ですか?10進数の精度を使用できる場合は必要になる場合がありますが(この場合も、8ビットまたは16ビット形式に出力するとその精度が失われます)、サンプルを使用して単純な計算を行うだけでは無駄になります。したがって、整数型に固執し、書き込み時にそれをchar / int8_tに変換することで、物事を大幅に簡略化できます。

于 2010-07-24T15:29:56.150 に答える
0

ここで手足を進めますが、符号付きの 16 ビット値が必要なため、これを試してください。

int16_t pcm = out * 256;
fwrite(&pcm, sizeof(pcm), 1, fo);

また、ファイルを正しくマークしたことを確認してください。適切なエンディアンネスを持つ生の PCM 符号付き 16 ビット。(編集: これは PCM には適用されません)

于 2010-07-24T15:33:39.780 に答える
0

このスレッドをゾンビ化するには:

WAV Wiki から:

WAV 形式にはいくつかの矛盾があります。たとえば、8 ビット データは符号なしで、16 ビット データは符号付きです。

于 2012-07-17T10:55:22.530 に答える