LinuxでC言語を使ってWAVファイルの再生・停止・一時停止をしようとしています。
再生・停止は行えるのですが、一時停止後、停止したところから再生がうまくいきません。
再生した秒数(ミリ秒まで)を測って、再生し終わった秒数からバイト数を求めて、その分を前詰めして再生させようとしています。
WAVファイルヘッダー 再生済み 未再生
├──────────┼──────┼──────┤
↓一時停止後再生
WAVファイルヘッダー 未再生
├──────────┼──────┤
再生済みバイト数の求め方は
バイト数=再生時間×8÷ビット数÷サンプリングレート÷チャンネル数
で求めています。
理論上この式であっていると思うのですが、ずれてしまいます。なぜか上記バイト数を÷2するとちょうど良いぐらいになります。
よろしくお願いします。
No.2ベストアンサー
- 回答日時:
なんか式が違っているような。
。。1回のサンプルで必要なバイト数
=(量子化ビット数÷8)×チャンネル数
1秒で必要なバイト数
=1回のサンプルで必要なバイト数 × サンプリング周波数
=(量子化ビット数÷8)×チャンネル数 × サンプリング周波数
n秒で必要なバイト数
=1秒で必要なバイト数 × n
nミリ秒で必要なバイト数
=n秒で必要なバイト数 ÷ 1,000
だと思います。
この回答への補足
教えて頂いた式を使ってやってみたのですが、
症状は変わりませんでした。
上記で求めた数値÷2をすればうまくいくのですが・・・
問題なのは「WAVを途中から再生させること」なのですが、
再生し終わったバイト数を求めてやることに問題があるのでしょうか?
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+求めたサイズ],再生データサイズ);
No.5
- 回答日時:
#3です。
>サンプリングレート:220050
間違ってません?
(一応確認)
#3のコードは問題ないように思えます。
とすると原因は他にありそうです。
どういうデバッグをしたのかわかりませんが、
・#2の計算式を実行するときの変数、戻り値を表示
(実際に計算をしている箇所で表示する)
・サウンド再生用関数に渡す内容をファイルに出力し、
プレーヤーで再生し、バイナリエディタで元のファイル と位置関係を比較する。
ということをやってみたらどうでしょうか。
(あまり大きなファイルでは使いにくいので、2~3秒のファイルを作るといいと思います)
No.6
- 回答日時:
>memcpy(&再生データ[44],&元データ[44+求めたサイズ],再生データサイズ);
この44というのは波形データの先頭ですか?
せっかくチャンクを探すコードを書いているのだから、波形データの先頭が44バイト目であると固定してしまうのはおかしいです。
WAVファイルのフォーマットとしては、"fmt "チャンクと"data"チャンクの間に別のチャンクが入る事もありえます。
あとは、元データの配列がshortだったりすると解決なんですが。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- YouTube YouTubePREMIUMについての質問です。Androidです。 動画を一時停止したままアプリを 1 2022/04/09 17:46
- 音楽・動画 tik tok 2 2023/07/03 23:03
- iPhone(アイフォーン) iPhoneのショートカット作成について 1 2022/06/01 17:17
- YouTube 最近スマホでYouTubeやツイッチで動画を見ていると急に一時停止することがあります。画面を触ってい 5 2023/07/09 18:23
- Chrome(クローム) Google Chrome の同期が必ず一時停止になってしまい困っています。 GoogleChrom 2 2023/02/04 16:45
- ノートパソコン Windows 10 動作改善方法 6 2023/04/26 22:30
- その他(パソコン・周辺機器) このUSBボリュームコントローラーはミュートを解除すると再生が開始すると書いてありますが、ミュートは 1 2023/05/07 18:55
- Chrome(クローム) Google Chrome の同期が必ず一時停止になってしまい困っています。 GoogleChrom 1 2023/02/05 09:59
- デスクトップパソコン Google Chrome の同期が必ず一時停止になってしまい困っています。 GoogleChrom 1 2023/02/05 19:19
- 運転免許・教習所 一時停止は視界が悪くてもやはり線のところで左右確認しないと捕まりますか? 一時停止の線のところに停車 18 2023/06/20 21:50
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
フォルダ内の動画ファイルを自...
-
iPhoneのショートカットでファ...
-
Windows Media Playerで全曲再生
-
パソコンでDVDを1.5倍速などで...
-
MP4のファイルが再生できません
-
wavファイル
-
Windows Media Player でAACを...
-
メディアプレーヤーでCDを再生...
-
windows media playerでCDを...
-
ムービーメーカーで画像の再生...
-
バーが動かない?
-
WindowsMediaPlayerで再生位置...
-
iPad proでisoファイルの方法。
-
ドライブレコーダーがパソコン...
-
DVD-Rに音楽は取り込めるのです...
-
Windows Media ...
-
mp3が再生できない
-
windows media player で再生...
-
m4aファイルの再生方法
-
オーディオファイルでエラーが...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
フォルダ内の動画ファイルを自...
-
パソコンでDVDを1.5倍速などで...
-
バーが動かない?
-
iPhoneのショートカットでファ...
-
windows media playerでCDを...
-
WindowsMediaPlayerで再生位置...
-
DVD-Rに音楽ファイル(WAV,MP3...
-
Windows Media ...
-
Windows10 DVDが見れない。
-
PS3で、USBメモリに取り...
-
DVD-Rに音楽は取り込めるのです...
-
Windows Media Playerの逆再生...
-
Windows Media Playerで全曲再生
-
ボイスレコーダーで録音したフ...
-
GOMプレイヤーのSWFファイルに...
-
音楽CDの再生が途中で止まる
-
知識のある方、教えてください。
-
音楽データ(MP3)をダウンロード...
-
mp3が再生できない
-
mp3アルバムを作ると勝手にフ...
おすすめ情報