質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

Q&A

解決済

2回答

1318閲覧

waveファイルの波形データを符号付き表現で取得したい

tuda905465

総合スコア7

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

0グッド

0クリップ

投稿2021/10/01 14:49

waveファイルを読み込むプログラムを作っていました。waveファイルのバイナリデータをfgetsで取得すると符号無し整数型になってしまうので、それだとそれだとopenalで再生できないので符号付き整数表現にしたかったです。
なのでsignedでポインタを宣言してmallocしたところ

ffffff9c,ffffffe1,ffffff9f,ffffffe2,ffffff9f,ffffffe2,ffffffa9,ffffffe1
のようなおかしな値が出力されました。unsginedで出力すると正常に出力できました。

符号無し表現を符号あり表現に変換することはできないのでしょうか?

c

1#include <stdio.h> 2#include <stdlib.h 3#include <string.h> 4 5int main(void) 6{ 7 //変数の宣言 8 int i; 9 int gomi; 10 11 //ファイル構造体の宣言 12 FILE *wave; 13 char fname[] = "square1.wav"; 14 15 16 //wavファイルをバイナリモードで開く、失敗するとNULL 17 wave = fopen(fname, "rb"); 18 if(wave == NULL) 19 { 20 printf("%s file not open!\n", fname); 21 return -1; 22 } 23 24//この行から波形データを取り込むまで読み飛ばしてもいい 25 //RIFF形式か調べる 26 int chank_ID[4] = {0x52,0x49,0x46,0x46}; 27 28 i=0; 29 while (i < 4) 30 { 31 if(chank_ID[i] != fgetc(wave)){ 32 printf("エラー\n"); 33 return -1; 34 } 35 i++; 36 } 37 printf("This file is RIFF\n"); 38 39 //全体のファイルサイズを調べる 40 int chank_size[4]; 41 42 i=3; 43 while (0 <= i) 44 { 45 chank_size[i] = fgetc(wave); 46 i--; 47 } 48 49 printf("This filesize is "); 50 i=0; 51 while (i < 4) 52 { 53 printf("%02x",chank_size[i]); 54 i++; 55 } 56 printf("\n"); 57 58 //waveか調べる 59 int format_ID[4] = {0x57,0x41,0x56,0x45}; 60 61 i=0; 62 while (i < 4) 63 { 64 if(format_ID[i] != fgetc(wave)){ 65 printf("エラー\n"); 66 return -1; 67 } 68 i++; 69 } 70 printf("This file is wave\n"); 71 72 //サブチャンク1IDを調べる 73 int sub_chank_1_ID[4] = {0x66,0x6D,0x74,0x20}; 74 75 i=0; 76 while (i < 4) 77 { 78 if(sub_chank_1_ID[i] != fgetc(wave)){ 79 printf("エラー\n"); 80 return -1; 81 } 82 i++; 83 } 84 printf("subchank1ID is OK\n"); 85 86 //サブチャンク1サイズを調べる 87 int sub_chank_1_size[4] = {0x10,0x00,0x00,0x00}; 88 89 i=0; 90 while (i < 4) 91 { 92 if(sub_chank_1_size[i] != fgetc(wave)){ 93 printf("Not supported\n"); 94 return -1; 95 } 96 i++; 97 } 98 printf("subchank1size is OK\n"); 99 100 //PCMフォーマットを調べる 101 int PCM_fomat[2] = {0x01,0x00}; 102 103 i=0; 104 while (i < 2) 105 { 106 if(PCM_fomat[i] != fgetc(wave)){ 107 printf("Not supported\n"); 108 return -1; 109 } 110 i++; 111 } 112 printf("PCMformat is OK\n"); 113 114 //ステレオかモノかを調べる 115 int channel_mono[2] = {0x01,0x00}; 116 int channel_stereo[2] = {0x02,0x00}; 117 int channel [2]; 118 119 fread(channel, sizeof(char), 2, wave); 120 if(memcmp(channel,channel_mono, 2) == 0){ 121 printf("This file is MONO\n"); 122 }else if (memcmp(channel, channel_stereo, 2) == 0) 123 { 124 printf("This file is STEREO\n"); 125 }else{ 126 printf("エラー\n"); 127 } 128 129 //サンプリング周波数を調べる 130 int sample_rate[4] = {0x44,0xAC,0x00,0x00}; 131 132 i=0; 133 while (i < 4) 134 { 135 if(sample_rate[i] != fgetc(wave)){ 136 printf("Not supported\n"); 137 return -1; 138 } 139 i++; 140 } 141 printf("sample_rate is 44100\n"); 142 143 //1秒あたりのバイト数の平均を表示 144 int average_byte[4]; 145 146 i=0; 147 while ( i < 4) 148 { 149 average_byte[i] = fgetc(wave); 150 i++; 151 } 152 153 printf("average_byte is "); 154 i=3; 155 while ( 0 <= i) 156 { 157 printf("%02x",average_byte[i]); 158 i--; 159 } 160 printf("\n"); 161 162 //ブロックサイズ、1サンプルあたりのビット数面倒なので読み飛ばす 163 i = 0; 164 while (i < 4) 165 { 166 gomi = fgetc(wave); 167 i++; 168 } 169 170 //サブチャンク2識別子 171 int sub_chank_2_ID[4] = {0x64,0x61,0x74,0x61}; 172 173 int x; 174 175 i = 0; 176 while (i < 4) 177 { 178 x = fgetc(wave); 179 if(sub_chank_2_ID[i] != x){ 180 printf("エラー\n"); 181 } 182 printf("%x\n",x); 183 i++; 184 } 185 printf("subchank2ID is OK\n"); 186 187 //波形データのバイト数を調べる 188 int sub_chank_2_size[4]; 189 190 i=0; 191 while ( i < 4) 192 { 193 sub_chank_2_size[i] = fgetc(wave); 194 i++; 195 } 196 197 printf("sub_chank_2_size is "); 198 i=3; 199 while ( 0 <= i) 200 { 201 printf("%02x",sub_chank_2_size[i]); 202 i--; 203 } 204 printf("\n"); 205 206 //波形データを取り込む 207 208 unsigned int wave_data_size = sub_chank_2_size[3]*0x1000000 + sub_chank_2_size[2]*0x10000 + sub_chank_2_size[1]*0x100 + sub_chank_2_size[0]; 209 unsigned int samplenumber = wave_data_size / 2; 210 printf("wavedatasize is %d\n",wave_data_size); 211 212 signed char *wave_data_1; 213 short int *wave_data_2; 214 215 wave_data_1 = (signed char*)malloc(sizeof(signed char) * wave_data_size); 216 217 i=0; 218 while (i < wave_data_size) 219 { 220 wave_data_1[i] = fgetc(wave); 221 printf("%x,",wave_data_1[i]); 222 i++; 223 } 224 225 free(wave_data_1); 226 227 228 229 return 0; 230}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2021/10/01 18:41

openal とは何でしょう。読み込んだ wave をどのように渡すことになっているのでしょうか。
tuda905465

2021/10/01 22:02

openalは音を扱えるようにするライブラリです。ですが現段階のプログラムではデータを配列にいれるということしかやっていません。
退会済みユーザー

退会済みユーザー

2021/10/01 23:35

とりあえず回答に対してなんかコメント貰えますか。 期待する回答じゃないなら、もうちょっと具体的に説明してください。
退会済みユーザー

退会済みユーザー

2021/10/01 23:41

OpenALのサンプル載ってるページ眺めてみたけど、普通にunsigned charでデータ読み込んでますが。
jimbe

2021/10/02 02:58

OpenAL でしたか。 >openalで再生できないので というのは、「"再生できない"と考えている」ということで、「実際にやってみて再生できなかった」ということでは無いということでしょうか。
tuda905465

2021/10/02 11:34

回答に時間がかかってすみませんでした。出力結果から配列に正しくデータが入ってないように見えたのでそれを直そうとしてたのですが、皆様の回答を見ていると自分がかんちがいしていたかもしれないと思いました。なので音を出すプログラムを作ったところ正常に動作しました。回答ありがとうございました。
退会済みユーザー

退会済みユーザー

2021/10/02 12:03 編集

> 配列に正しくデータが入ってないように見えたので 開発環境は知りませんが、もしVisualStudioを使っているなら、デバッグ実行して変数とメモリビューを見るのが手っ取り早いです。
jimbe

2021/10/02 12:40

見た目全然違うとビックリしてしまうのは分かります^^;
tuda905465

2021/10/02 23:15

Xcodeにもデバッグエリアに変数の中身を見る機能があったようです。それで変数の中身を見たところ配列に正しくデータが入っていることが確認できました。
guest

回答2

0

ベストアンサー

signed char a=-1;
とすると、(ふつーのシステムなら)charに保存されるピットパターンは0b11111111となるでしょう。
さて、、printf("%d",a);ではなにが表示されることが期待されるかというと、aは符号ありの値なのですから
255
ではなくて、
-1
ですね。
%xや%dは、符号ありintを前提に動作します。
ここに符号ありのchar(やshort)を与えた場合でも正しく負数を表示するため、「符号拡張」という操作が行われます。(2の補数を用いた処理系において)負数の最上位ビットは符号を表すことになります。この符号ビットを、char(やshort)より大きいビット位置に全部コピーします。
例えば、signed charで0b10000000であれば、intに拡張するとsigned charの最上位の1でintの上位を埋めて0b11111111 11111111 11111111 10000000とした上でprintfの処理をします。

これが

ffffff9c,ffffffe1,ffffff9f,ffffffe2,ffffff9f,ffffffe2,ffffffa9,ffffffe1

のようなおかしな値が出力されました。unsginedで出力すると正常に出力できました。

の仕組み。実はそうなるべくしてなっているので、決して「おかしな値」ではないです。
unsignedでは符号がないので符号拡張は行われず、「正常に出力」されることになります。


さて、ちゃぶ台返し
今回解決したい問題は
・音を出す
・unsigned charの値を(あなたが思ったように)適切に表示する
どちらでしょう? なんだか前者のような気がしますが...

そうであれば、質問には情報が足りません。

「再生できない」とは、現象としてどういうことが起こることを言っていますか?
・プログラムがエラーを起こして動かなくなる
・うんともすんとも音が出ない
というようなことだとすると、データ型は関係ない(「符号無し表現を符号あり表現に変換すること」は解決にならない)可能性が出てきます。

投稿2021/10/01 23:58

thkana

総合スコア7703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

printfで、wave_data_1[i]を%xに対応させる時にintに変換されてそのように出力されているのだと思います。
charの0x9cは-100で、intだと-100は0xffffff9cとなります。

とりあえず、出力時だけunsignedにキャストすればよいのではないかと。

c

1printf("%x,", (unsigned char)wave_data_1[i]);

投稿2021/10/01 18:06

編集2021/10/01 18:11
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問