LinuxでC言語を使ってWAVファイルの再生・停止・一時停止をしようとしています。
再生・停止は行えるのですが、一時停止後、停止したところから再生がうまくいきません。
再生した秒数(ミリ秒まで)を測って、再生し終わった秒数からバイト数を求めて、その分を前詰めして再生させようとしています。
WAVファイルヘッダー 再生済み 未再生
├──────────┼──────┼──────┤
↓一時停止後再生
WAVファイルヘッダー 未再生
├──────────┼──────┤
再生済みバイト数の求め方は
バイト数=再生時間×8÷ビット数÷サンプリングレート÷チャンネル数
で求めています。
理論上この式であっていると思うのですが、ずれてしまいます。なぜか上記バイト数を÷2するとちょうど良いぐらいになります。
よろしくお願いします。
No.2ベストアンサー
- 回答日時:
なんか式が違っているような。
。。1回のサンプルで必要なバイト数
=(量子化ビット数÷8)×チャンネル数
1秒で必要なバイト数
=1回のサンプルで必要なバイト数 × サンプリング周波数
=(量子化ビット数÷8)×チャンネル数 × サンプリング周波数
n秒で必要なバイト数
=1秒で必要なバイト数 × n
nミリ秒で必要なバイト数
=n秒で必要なバイト数 ÷ 1,000
だと思います。
この回答への補足
教えて頂いた式を使ってやってみたのですが、
症状は変わりませんでした。
上記で求めた数値÷2をすればうまくいくのですが・・・
問題なのは「WAVを途中から再生させること」なのですが、
再生し終わったバイト数を求めてやることに問題があるのでしょうか?
No.6
- 回答日時:
>memcpy(&再生データ[44],&元データ[44+求めたサイズ],再生データサイズ);
この44というのは波形データの先頭ですか?
せっかくチャンクを探すコードを書いているのだから、波形データの先頭が44バイト目であると固定してしまうのはおかしいです。
WAVファイルのフォーマットとしては、"fmt "チャンクと"data"チャンクの間に別のチャンクが入る事もありえます。
あとは、元データの配列がshortだったりすると解決なんですが。
No.5
- 回答日時:
#3です。
>サンプリングレート:220050
間違ってません?
(一応確認)
#3のコードは問題ないように思えます。
とすると原因は他にありそうです。
どういうデバッグをしたのかわかりませんが、
・#2の計算式を実行するときの変数、戻り値を表示
(実際に計算をしている箇所で表示する)
・サウンド再生用関数に渡す内容をファイルに出力し、
プレーヤーで再生し、バイナリエディタで元のファイル と位置関係を比較する。
ということをやってみたらどうでしょうか。
(あまり大きなファイルでは使いにくいので、2~3秒のファイルを作るといいと思います)
No.3
- 回答日時:
#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+求めたサイズ],再生データサイズ);
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
フォルダ内の動画ファイルを自...
-
windows media playerでCDを...
-
パソコンでDVDを1.5倍速などで...
-
メディアプレーヤーでDVD再生時...
-
windows10でminiDVDを再生や保...
-
windows7でのモノラル音声再生
-
バーが動かない?
-
DVD-Rに音楽は取り込めるのです...
-
音楽データ(MP3)をダウンロード...
-
WindowsMediaPlayerで再生位置...
-
ファイナライズ処理のやり方を...
-
Windows Media Playerの逆再生...
-
Windows Media ...
-
メディアプレーヤーのコマ送り
-
PCにCDを入れると歌詞が出...
-
WMPで作成したCD-Rについて
-
音楽CDをカーナビのCDプレーヤ...
-
DVD挿入時に自動起動したくない
-
ムービーメーカーで画像の再生...
-
メディアプレーヤーでCDを再生...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
フォルダ内の動画ファイルを自...
-
パソコンでDVDを1.5倍速などで...
-
Windows Media ...
-
windows media playerでCDを...
-
DVD-Rに音楽ファイル(WAV,MP3...
-
バーが動かない?
-
音楽データ(MP3)をダウンロード...
-
WindowsMediaPlayerで再生位置...
-
iPhoneのショートカットでファ...
-
ボイスレコーダーで録音したフ...
-
Windows10 DVDが見れない。
-
windows media player で再生...
-
DVD-Rに音楽は取り込めるのです...
-
Windows Media Playerの逆再生...
-
ファイナライズ処理のやり方を...
-
外付けハードディスクに入れた...
-
音楽CDの再生が途中で止まる
-
windows7でのモノラル音声再生
-
DVD再生時の音声が小さい
-
mp3アルバムを作ると勝手にフ...
おすすめ情報