情報処理4レポート課題(10)の解答例

更新:2008年11月28日


  1. bfile1_4.cを書き換えて,short型1000個の配列を用意して, そのi番目の要素に,2*iを設定して, ファイルshort1000-1.datに出力するプログラムを作成して下さい.
    report10-1.c
    #include<stdio.h>
    #include<stdlib.h>
    
    int main(void){
    	FILE *fp;
    	int chk, i;
    	short a[1000];
    
    	for(i=0;i<1000;i++){
    		a[i]=2*i;
    	}
    	
    	fp=fopen("short1000-1.dat", "wb");
    	if(fp==NULL){
    		printf("File Can't Open\n");
    		exit(1);
    	}
    	chk=fwrite(a, sizeof(a[0]), sizeof(a)/sizeof(a[0]), fp);
    	if(chk<sizeof(a)/sizeof(a[0])){
    		printf("Write Error(%d)\n", chk);
    	}
    	fclose(fp);
    	return 0;
    }
    
    1. 次の作業を行って下さい.
      1. このファイルをダウンロードする.
      2. スクリーン右上のスピーカアイコンをクリックしてボリュームを最大値に設定する.
      3. モニタスクリーン下部にあるVolumelボタンを押して,ボリュームを適度に設定する.
      4. ファイルsample.rawが保存されているディレクトリで,次を実行する:
        sox -V -r 8000 -s -w -c 1 sample.raw -t ossdsp /dev/dsp0
        音が鳴ったことを確認して下さい. 音が鳴らない場合には,上の作業を確認して下さい.
        • V:動作表示
        • r:サンプリングレート指定
        • s:符号付きデータ
        • w:16bitデータ
        • c:チャネル数指定
        • t:ファイルタイプ
        • ossdsp:OSS /dev/dsp デバイスドライバ

      解答例は省略されています。
    2. bfile1_4.cを書き換えて,short型1000個の配列を用意して, その番目の要素に,を設定して, ファイルshort1000-2.datに出力するプログラムを作成して下さい. ただし,小数計算を明示するために、10,2を10.0,2.0と記述し、 関数sinの引数にdouble型を設定するために idouble型に変換し, 計算結果をshort型配列に格納するために short型に代入するための代入演算子の右辺全体を short型に型変換して下さい. ここで例えば,double型変数xint型に型変換して,int型変数nに代入するには
      double x=1.2;
      int n;
      n=(int)(x);
      
      のようにします.
      report10-2-2.c
      #include<stdio.h>
      #include<stdlib.h>
      #include<math.h>
      
      int main(void){
      	FILE *fp;
      	int chk, i;
      	short a[1000];
      
      	for(i=0;i<1000;i++){
      		a[i]=(short)(10.0*sin(2.0*(double)(i)));
      	}
      	
      	fp=fopen("short1000-2.dat", "wb");
      	if(fp==NULL){
      		printf("File Can't Open\n");
      		exit(1);
      	}
      	chk=fwrite(a, sizeof(a[0]), sizeof(a)/sizeof(a[0]), fp);
      	if(chk<sizeof(a)/sizeof(a[0])){
      		printf("Write Error(%d)\n", chk);
      	}
      	fclose(fp);
      	return 0;
      }
      
    3. サンプリングレート8000[Hz],モノラル,16bit符号付きデータとして, ピッチ1[kHz]一定,音量最大一定で2秒間の音声データファイルpcm-8000Hz-1c-2byte-1000Hz-2sec.rawを出力するプログラムを作成して下さい. 先に次の問題から解くことを勧めます。
      report10-2-3.c
      #include<stdio.h>
      #include<math.h>
      
      int main(void){
      	short a[16000];
      	int i;
      	FILE *fp;
      	fp=fopen("pcm-8000Hz-1c-2byte-1000Hz-2sec.raw", "wb");
      	for(i=0;i<16000;i++){
      		a[i]=(short)(32767.0*sin(2*M_PI*1000.0*((double)i)/8000.0));
      	}
      	printf("%d %d\n", sizeof(a[0]), sizeof(a));
      	fwrite(a, sizeof(a[0]), sizeof(a)/sizeof(a[0]), fp);
      	fclose(fp);
      	return 0;
      }
      
    4. 次のからまでに適切に埋めて下さい。

      課題音声のピッチが(a)[Hz]ということは1秒間に(b)回振動することを表し, その周期は(c)[sec]となります.課題音声の振幅が(d)なので, その正弦波を時刻[sec]の関数とするとを用いて (e)と表されます.

      課題音声のサンプリングレートが(f)[Hz]ということは, 1秒間に(g)個のデータを用いることになり, 課題では(h)[sec]の音声データが必要なので, 課題音声のフォーマットである(i)[bit]符号付きデータを(j)個格納するための配列を用意することになります. (i)[bit]は(k)バイトなので,(i)[bit]符号付きデータを表すために(l)型を用います. したがって,(l)型を(j)個要素に持つ配列を用います. ここで,その配列の名前をwaveとします.

      課題音声のサンプリングレートが(f)[Hz]なので, 配列waveの要素1つで(m)[sec]分のデータを保持することになります. よって,配列wavei番目の要素は (n)秒目のデータを保持することになります. したがって,先程得た正弦波の式を用いると 配列wavei番目の要素の値は, (o)と表されます.

      ここで,C言語の型規則にしたがうために,正弦波の式中の整数は, 例えば2を2.0のように,double型として認識されるように, また,idouble型に型変換してから計算されるように, さらに,配列の要素wave[i]に代入する際に, short型に型変換してから代入して下さい. また,円周率については,3.14としてもかまいませんが, マクロ定数M_PIを用いるとより正確に計算できます.


      課題音声のピッチが(A:1)[kHz]ということは1秒間に(B:1000)回振動することを表すので、 振幅を仮にとすると、 その正弦波は時刻[sec]の関数として (C:)と表されます.

      課題音声のサンプリングレートが(D:8000)[Hz]ということは, 1秒間に(E:8000)個のデータを用いることになり, 課題では(F:2)秒間の音声データが必要なので, 課題音声のフォーマットである(G:16)[bit]符号付きデータを(H:16000)個格納するための配列を用意することになります. (G:16)[bit]は(I:2)バイトなので,(G:16)[bit]符号付きデータを表すために(J:short)型を用います. したがって,(J:short)型を(H:16000)個要素に持つ配列を用います. ここで,その配列の名前をwaveとします.

      (J:short)型で表すことのできる最大値は(K:32767)なので、 先の正弦波の振幅は(K:32767)となります。

      課題音声のサンプリングレートが(D:8000)[Hz]なので, 配列waveの要素1つで(L:1/8000)[sec]分のデータを保持することになります. よって,配列wavei番目の要素は (M:i/8000)秒目のデータを表すことになります. したがって,先程得た正弦波の式を用いると 配列wavei番目の要素の値は, (N:)と表されます.


以下は皆さんの幾つかの考察・感想に対するコメントです.
型による最大値の違いが 分からなかった。
前回のレポート課題を復習して下さい。
型が違うことによって 音の高さが違うことがわかりました。short int doubleの順で音が低く、長くなります。バイト数の違いと音の高さ、長さはどうして関係 してくるのでしょうか??
まず、正しいプログラムはshort型2バイトで作成していて、 出力ファイルをsoxコマンドに渡すときにもデータが2バイトで格納されていると仮定しています。 それぞれshort:2バイト,int:4バイト,double:8バイトで書かれたものを 2バイトで書かれていると思うと、その長さはそれぞれ short:同じ,int:2倍,double:4倍になるので、 長さが代わります。 音の高さについては一概にshort,int,doubleの順で低くなるとは云えないと思います。 まずint型については、ビッグエンディアンで考えて下位2バイトに 本来の波形データが格納されていて上位2バイトには0x0が格納されているか、 0xffffが格納されていて本来の波形データではないので歪んだ波形になります。 ただしその歪みは規則的なので、低く聞こえるかも知れません。 さらにdouble型についてはもはや、char,short,intのような整数型とは全く異なる データ格納形式をとっているので、得られたデータが果たしてどのように聞こえるのかはよく調べてみないと分かりません。
問題2-2ですが、この書き換えたもののバイナリを見たのですが、これがあっているのか どうか分かりませんでした。関数電卓で調べて照らし合わせるのが早いのでしょうか。
ファイル出力したものと同じ値を十進整数で画面表示して, 照らし合わせるのが良いと思います.
今回の課題の一番で確認せよとの事だったので確認しましたと書いたのですが、プログラ ムものせたほうが良かったでしょうか?次から同じような課題の出され方があった場合の 参考にするので是非授業中にでも指摘してくれると助かります。
「確認せよ」とは2-2のことですね。これについてはプログラム作成ではないので、 のせるプログラムはないと思いますよ。
sinという関数をつかったが始めに#includeは付けるべきか迷った。付ける必要 はあるのですか??そしてコンパイルする時にも特有のコンパイルの仕方をする必要はあ りますか??去年習いましたがすこし忘れてしまいました。
つける必要があります.コンパイル時にオプション-lmをつけます.
「2^16を軸の上下で分けたら2^8と2^8になる」と思ってしまったので、振幅32767の所を2 55としてしまった。 振幅は音の大きさに関係するので最初に音が出なかったのはこれが原因だったのかもしれ ない。
そうだと思います。
鳴っている時間を短くしていって、どこまで聞こえるかを試してみたところ、要素数2、 「i<2」の2波長分まで聞こえました。1/4000秒を肌で感じれた気がします。 でも本当に1/4000秒間しか音が出ていないのか疑問です。
1/4000秒というのは単に、PCがスピーカに出そうとしている時間であって、 スピーカが1/4000秒間だけ振動するということはないと思うので、 実際にはもっと長く音が鳴っていると思います。
いろいろ関数あたりをがちゃがちゃいじってtanとかにしてみたが、 汚い音が発せられたりした。
tan関数は値域が-∞から∞かつ不連続なので音が汚くなってしまいますね。 sinとcosで組合せるのがよいと思います。
アナログの音声をサンプリングした数値データを同じように再生したら音声が出るのだろ うか。
出ます。
ピ〜って音じゃなくて、↑ピ〜↑って音出したかったんですけど、いろいろやってもわか りませんでした。
ええと、高い音ってことでしょうか。ならばピッチを上げれば良いと思います。
今回、音声ファイルとして用いたRAWファイルについて調べてみました。 RAWは画像用の拡張子と、しらべたらでていたんですが、他のpngとかjpegなどの拡張子にも、音声をのせることはできるのでしょうか?
まずrawとは「生」「未加工の」を意味します。 RAWファイルとは書式などを一切考えずに データがただそのまま格納されていることを意味し、 その中身が音声か画像かは関係ありません。 音声RAWファイルは 音声波形だけが格納されているもので その音声のサンプリングレート、量子化ビット数、時間などの情報が格納されていません。 よって音声RAWファイルを再生するには、 これらの正しい情報を予め知っておくか適当に決めなければなりません。 画像ファイルとしてのRAWファイルは画像情報だけが格納されているもので、 その画像の大きさ、色数などの情報が格納されていません。 よって画像RAWファイルを表示するには、 これらの正しい情報を予め知っておくか適当に決めなければなりません。 本来、拡張子とファイルの中身は別物なので、 音声ファイルの拡張子をtxtやjpgにしてもそれは音声ファイルです。 しかし、OSの中には拡張子だけでそのファイルの種類を決めつけるものもあり、 これを悪用するケースもありますね。
余分なことでしたが、最大値を出したかったので2進数から10進数に直すプログラミング を作ってみました。でもいらなかったし失敗しました。ちょっとショックです。
今回は不要だったかも知れませんが、いつか役立つ日がくるかも知れませんし、 何よりも、そのプログラミングを通して身についた知識・技術・経験は 今の自分に役立っていると思いますよ。
音の出る原理がよくわからなかった。
皆さんの作ったファイルを、soxコマンドが解釈してPCのサウンドボードに送り、 PCのサウンドボードは送られたデータをアナログ電気信号に変換してスピーカに送り、 スピーカは電気信号を物理振動に変換して振動板を震わせ、 振動板は隣接する空気を振動させその振動が自分の耳に届いて鼓膜が振動し、 鼓膜の振動が脳に伝わって「音が鳴っている」と知覚します。 (後半ははったりなので自分で調べて下さい。)
根気しだいでシンセサイザーに勝てそうですね
その根気が...。
問題2-1で音を鳴らす時に、デスクトップの上のパネルが消えてしまってものすごく焦り ました;;
言い回しが過去形だということは何とかなったのですよね。良かったです。
別のやさしい音にしてくれたら、僕の耳が喜びます。
是非,やさしい音を出すプログラムに挑戦して下さい.
向かいの人のスピーカーの音がうるさくてマジ切れそうになった!
キレる前にやさしく 「ボリューム下げてね」と.
課題3でずっとa[16000]をint型でやっていたら全っ然音が違っ てて、しばらく間違いを見付けられなかったのでだんだん楽しくなってしまった。 何事も楽しむ姿勢があ痔時だと思う。
楽しむことは大事ですよね。「あ痔時」の意味は分かりませんが。
理論が完璧で、実技も完璧なら一番いいのだけどなかなかそう簡単には いかないものだと感じました。
たしかにその通りですね。
バイナリファイルをいじるプログラムは間違いが探しにくいです。。。
そうですね。心してかからねばなりません。
自宅で問題を解いたのでrawファイルの再生するアプリケーションを探すのに苦労した。
よろしければ何を使ったのか教えて下さい。
正直、付いていけません、ここもでのおさらい的な物がとても欲しいです。 助けてください!!
試験日の前の週にこの科目をまとめるので、それがいわばおさらいになると思いますが、 それを待っていたのでは遅いと思います。 後期は途中で冬期休暇を挟むのでそこでしっかりと自己学習することをお勧めします。
トイレに行きたかったのだがヒントが出るかもッという感じだったので我慢した↓↓ キーボードを打つてが震えた...
手が震える程我慢して大変でしたね。 漏らさずに済みましたか?
左肩だけが凝っていてパソコン辛いです。
肩こりの原因がPC操作なのならば, 姿勢が問題かも知れません. 知らず知らずの内に肩を上げているのかも知れません. 肩を下げて作業しましょう.
パソコンの問題で鳴らない時に変えるのが面倒臭いです。
そうですね。 でも、いかんともしがたいので当座、 以前に音が鳴ることを確認したPCを常に使うのはどうでしょう。
暖房が顔に当たるのがいやです…ぼうっとしてしまいます。
席を変えるしか手はないですねぇ.
パソコン室の空調はめちゃくちゃだと思います
私にはそれほどめちゃくちゃだとは思いませんが、 もしそう思うのならばネットワークサービス課に 報告してみてはどうでしょう。
パソコンにかじりつきなので目が痛いです。
目とディスプレイの距離をとって、 意識してまばたきするようにしましょう。
回路理論演習の課題が難しいです。溶けそういや、溶けません。 ところで、 でも!
回路理論演習は来年の通信工学実験で非常に役立つと思うので頑張って下さいね。 で、「でも」、何なのでしょうか。それとも、
もうすぐ12月になるが個人的には好きな季節なので楽しみだ。
あと数週間で実家に一年ぶりに帰省できると思うとフルテンションで脱ぎたくなる。
春、夏と帰らなかったのですね。成人式ですか? 公共の場で脱ぐのはやめておきましょう。
スノボですか?
朝シャワーを浴びるのは寒すぎて限界です。
冬は風呂ですな。
大人って良かった。
???。まあ、良かったですね。
いい歳してポケモンに熱中してる友達が今日はメタモンについて力説してきました。
あまりにひどくなければ, ある程度話を聞いて上げるのも友情だと思います.
海の上で食べるぷっちょは最高においしいです。
海水で喉が乾いているときに唾液補給にもなって良いですね.
まだ空腹とうまく付き合えません(泣)
幾つになっても難しいと思います。
最近お腹がすぐに減ってしまいます。食べざかりでしょうか?
食べざかりか、例の「ばあさん、飯はまだかね?」って奴かも知れません。
生協でメロンパン祭がやってました。参加しようと思います。
メロンパンおいしいですよね。 セブンの発酵バターメロンパンが好きです。
今やってるドラマの中で一番面白いのは"ブラディマンデイ"です。
ドラマ暫く見てないなぁ(遠い目)。
今度、『ルミネ the 吉本』に行ってきます。おすすめのお笑い芸人を教えてください。
私が好きなのは、ラーメンズ、アンジャッシュ、鳥居みゆき、サンドウィッチマン、昔のダウンタウン、そのくらいでしょうか。吉本じゃないのが多いなぁ。今、思い浮かばない。
あと最近アイマス始めてとりあえずミキ終りました。先生方の間でもやってる方はいます か?
何のことか分からずググってみました....。
前世で自分は世界を救う勇者だったような気がします。現世では何を為せばよいのでしょ うか?
戦わなければ生き残れないのでしょうか?
生きること自体が戦いだと思います。
現世でも勇者になれるように精進するのが良いかと思います。 試しにプログラミングで勇者になるのはどうでしょうか。
来週、行田先生が休講なので4限しかありません。
もっと早く云ってくれれば....

何かありましたら、 まで。