- ベストアンサー
LINUXでのWAV再生・停止・一時停止の方法とは?
- LinuxでC言語を使ってWAVファイルの再生・停止・一時停止の方法を探っています。
- 再生と停止はできるが、一時停止後の再生がうまくいかない問題があるようです。
- 再生済みバイト数を求めるための式に誤りがある可能性があり、式の修正が必要です。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
なんか式が違っているような。。。 1回のサンプルで必要なバイト数 =(量子化ビット数÷8)×チャンネル数 1秒で必要なバイト数 =1回のサンプルで必要なバイト数 × サンプリング周波数 =(量子化ビット数÷8)×チャンネル数 × サンプリング周波数 n秒で必要なバイト数 =1秒で必要なバイト数 × n nミリ秒で必要なバイト数 =n秒で必要なバイト数 ÷ 1,000 だと思います。
その他の回答 (5)
>memcpy(&再生データ[44],&元データ[44+求めたサイズ],再生データサイズ); この44というのは波形データの先頭ですか? せっかくチャンクを探すコードを書いているのだから、波形データの先頭が44バイト目であると固定してしまうのはおかしいです。 WAVファイルのフォーマットとしては、"fmt "チャンクと"data"チャンクの間に別のチャンクが入る事もありえます。 あとは、元データの配列がshortだったりすると解決なんですが。
- ngsvx
- ベストアンサー率49% (157/315)
#3です。 >サンプリングレート:220050 間違ってません? (一応確認) #3のコードは問題ないように思えます。 とすると原因は他にありそうです。 どういうデバッグをしたのかわかりませんが、 ・#2の計算式を実行するときの変数、戻り値を表示 (実際に計算をしている箇所で表示する) ・サウンド再生用関数に渡す内容をファイルに出力し、 プレーヤーで再生し、バイナリエディタで元のファイル と位置関係を比較する。 ということをやってみたらどうでしょうか。 (あまり大きなファイルでは使いにくいので、2~3秒のファイルを作るといいと思います)
- xcrOSgS2wY
- ベストアンサー率50% (1006/1985)
使用しているwavファイルのデータ自体がおかしいということはありませんか? wavファイルの大きさ、諸元、実際に再生したときの再生時間(実測値)は矛盾なく一致していますか?
補足
WAVファイルのヘッダー情報がおかしいと再生ができません。 他のプレイヤーで問題なく再生できるのでファイル自体に問題はないと考えます。
- ngsvx
- ベストアンサー率49% (157/315)
#2です。 計算式は、#2のもので間違いありません。 この式を使ってズレるのなら、原因は他にあると思います。 例えば、 ・経過時間のカウントが間違えている。 ・計算式中の変数を間違えている。 (モノラルデータをステレオで計算している) ・サウンド再生用関数への引数の渡し方を間違えている。 などです。 (他にもあるかもしれません) 怪しいのは、2番目でしょうね。 変数の値はどこから持ってきましたか?
補足
>経過時間のカウントが間違えている。 経過時間を出力して確認しているので大丈夫だと思われます。 >計算式中の変数を間違えている。 WAVファイルのヘッダーから取ってきています。 ビット数:16ビット サンプリングレート:220050 チャンネル数:2 のファイルでテストしています。 上記情報を取るためのロジックは以下のとおり。 typedef struct { FILE* fp; /* ファイル構造体 */ short is_pcm; /* PCM フォーマットの場合は 1、それ以外は 0 */ short channel; /* モノラルの場合は 1、ステレオの場合は 2 */ int rate; /* サンプリング周波数 */ short bits; /* 量子化ビット数 */ long offset; /* ファイル先頭から PCM データまでのオフセット */ int len; /* PCM データ部の長さ */ } WAVE; wave_readFile( char* fname ) { char buf[32]; int len; if ( ( wave.fp = fopen( fname, "r" ) ) == NULL ) { fprintf( stderr, "Failed to open %s\n", fname ); return -1; } /* 先頭 4 バイトが "RIFF" であることを確認 ( 更に 4 バイトスキップしておく ) */ fread( buf, 8, 1, wave.fp ); if ( strncmp( buf, "RIFF", 4 ) != 0 ) { fprintf( stderr, "Specified file is not RIFF file.\n" ); fclose( wave.fp ); return -1; } /* 次の 4 バイトが "WAVE" であることを確認 */ fread( buf, 4, 1, wave.fp ); if ( strncmp( buf, "WAVE", 4 ) != 0 ) { fprintf( stderr, "Specified file is not WAVE file.\n" ); fclose( wave.fp ); return -1; } /* fmt チャンクを探す */ while ( 1 ) { fread( buf, 8, 1, wave.fp ); len = *( int* )( &buf[4] ); if ( strncmp( buf, "fmt ", 4 ) != 0 ) { if ( fseek( wave.fp, len, SEEK_CUR ) == -1 ) { fprintf( stderr, "Failed to find fmt chunk.\n" ); fclose( wave.fp ); return -1; } } else break; } /* WAVE フォーマットを読み込む */ fread( buf, len, 1, wave.fp ); wave.is_pcm = *( ( short* )( &buf[0] ) ); wave.channel = *( ( short* )( &buf[2] ) ); wave.rate = *( ( int* )( &buf[4] ) ); wave.bits = *( ( short* )( &buf[14] ) ); if ( wave.is_pcm != 1 ) wave.is_pcm = 0; /* data チャンクを探す */ while ( 1 ) { fread( buf, 8, 1, wave.fp ); len = *( int* )( &buf[4] ); if ( strncmp( buf, "data", 4 ) != 0 ) { if ( fseek( wave.fp, len, SEEK_CUR ) == -1 ) { fprintf( stderr, "Failed to find data chunk.\n" ); fclose( wave.fp ); return -1; } } else break; } wave.len = len; if ( ( wave.offset = ftell( wave.fp ) ) == -1 ) { fprintf( stderr, "Failed to find offset of PCM data.\n" ); fclose( wave.fp ); return -1; } return 0; } >サウンド再生用関数への引数の渡し方を間違えている。 write関数に渡しているWAVデータの作り方に間違いがあることは考えたのですが、恐らく大丈夫です。 /* 元データよりヘッダー部コピー */ memcpy(再生データ,元データ,44); /* 音声部分コピー */ memcpy(&再生データ[44],&元データ[44+求めたサイズ],再生データサイズ);
- xcrOSgS2wY
- ベストアンサー率50% (1006/1985)
質問の中の式はおかしいですよね。(サンプリングレートで割ると、サンプリングレートが高いほどバイト数が減ってしまいますよ。ビット数、チャンネル数についてもしかり。) もう少し質問を整理してください。
補足
元々は 再生時間=8×データサイズ÷ビット数÷サンプリングレート÷チャンネル数 =8×データサイズ÷(ビット数×サンプリングレート×チャンネル数) の計算式からデータサイズを求める計算式をだしました。 これが間違っていますか?
補足
教えて頂いた式を使ってやってみたのですが、 症状は変わりませんでした。 上記で求めた数値÷2をすればうまくいくのですが・・・ 問題なのは「WAVを途中から再生させること」なのですが、 再生し終わったバイト数を求めてやることに問題があるのでしょうか?