情報処理4レポート課題(13)

更新:2009年1月13日


  1. bfileo1_7_2.cとbfileo1_8_2.cを参考にして、
    1. バイナリファイルfor_report13-1-0.datから、
      • 2バイト入力してshort型変数data_s1に格納し、
      • 5文字入力してchar型配列sに格納して終端文字を設定し、 s"info4"が一致しなければ その旨のメッセージを画面表示してプログラムを終了し、 そうでなければ、
      • 2バイト入力してshort型変数data_s2に格納し、 data_s2data_s1の2倍でなければ その旨のメッセージを画面表示してプログラムを終了し、 そうでなければ、
      • data_s2に格納されている値分の int型変数を格納する領域を確保してから、
      • ファイルから4バイトdata_s2個分入力したものを確保した領域に格納し、
      • data_s1, s, data_s2についてはそのままで、 4バイトdata_s2個分についてはそれぞれを倍してから バイナリファイルreport13-1-0new.datに出力
      してください。 正しく計算するために、係数中の整数定数には小数点を用い、 整数変数を一旦double型に変換してから計算し、 あらためて配列の要素に代入する際にint型に変換することに注意してください。
    2. 作成したプログラムを用いて、バイナリファイルfor_report13-1-1.datについて入力してみて下さい。
    3. 作成したプログラムを用いて、バイナリファイルfor_report13-1-2.datについて入力してみて下さい。

    report13-1.c
    #include<stdio.h>
    #include<stdlib.h>
    
    int main(void){
    	FILE *fp;
    	int chk;
    	short data_s1, data_s2;
    	char s[6];
    	int *array_i, i;
    
    	fp=fopen("for_report13-1-0.dat", "rb");
    	if(fp==NULL){
    		printf("File Can't Open for input file\n");
    		exit(1);
    	}
    	chk=fread(&data_s1, sizeof(data_s1), 1, fp);
    	if(chk<1){
    		printf("Read Error for data_s1\n");
    		exit(1);
    	}
    	chk=fread(s, sizeof(s[0]), 5, fp);
    	if(chk<5){
    		printf("Read Error for s\n");
    		exit(1);
    	}
    	s[5]='\0';
    	if(strcmp(s, "info4")!=0){
    		printf("Not \"info4\" but %s\n", s);
    		exit(1);
    	}
    	chk=fread(&data_s2, sizeof(data_s2), 1, fp);
    	if(chk<1){
    		printf("Read Error\n");
    		exit(1);
    	}
    	if(data_s2!=2*data_s1){
    		printf("data_s2!=2*data_s1; data_s2:%d, data_s1:%d\n",
    			data_s2, data_s1);
    		exit(1);
    	}
    	array_i=malloc(data_s2*sizeof(int));
    	if(array_i==NULL){
    		printf("out of Memory\n");
    		exit(1);
    	}
    	chk=fread(array_i, sizeof(array_i[0]), data_s2, fp);
    	if(chk<data_s2){
    		printf("Read Error\n");
    		exit(1);
    	}
    	fclose(fp);
    
    	for(i=0;i<data_s2;i++){
    		array_i[i]=(int)(array_i[i]*(3.0*((double)i)+0.8));
    	}
    
    	fp=fopen("report13-1-0new.dat", "wb");
    	if(fp==NULL){
    		printf("File Can't Open\n");
    		exit(1);
    	}
    	chk=fwrite(&data_s1, sizeof(data_s1), 1, fp);
    	if(chk<1){
    		printf("Write Error\n");
    		exit(1);
    	}
    	chk=fwrite(s, sizeof(s[0]), strlen(s), fp);
    	if(chk<strlen(s)){
    		printf("Write Error\n");
    		exit(1);
    	}
    	chk=fwrite(&data_s2, sizeof(data_s2), 1, fp);
    	if(chk<1){
    		printf("Read Error\n");
    		exit(1);
    	}
    	chk=fwrite(array_i, sizeof(array_i[0]), data_s2, fp);
    	if(chk<data_s2){
    		printf("Read Error\n");
    		exit(1);
    	}
    	fclose(fp);
    	return 0;
    }
    
  2. 次の作業を行って下さい.
    1. このファイルをダウンロードする.
    2. スクリーン右上のスピーカアイコンをクリックしてボリュームを最大値に設定する.
    3. モニタスクリーン下部にあるVolumelボタンを押して,ボリュームを適度に(3くらい?)に設定する.
    4. ファイルsample.wavが保存されているディレクトリで,次を実行する:
      xmms sample-decay.wav &
      音が鳴ったことを確認して下さい. 音が鳴らない場合には,上の作業を確認して下さい. もしくは、次のコマンドを試してみて下さい。
      sox -V sample-decay.wav -t ossdsp /dev/dsp0
    5. ファイルsample-decay.wavをemacsでバイナリーモードで閲覧してみて下さい。
  3. レポート課題(11)の問3で作成したWAVファイルpcm-8000Hz-1c-2byte-1000Hz-2sec.wavを入力して、 音量が線形に減衰して最終的に音量0になるように加工してバイナリファイルpcm-8000Hz-1c-2byte-1000Hz-2sec-decay.wavを出力するプログラムを作成して下さい。 次の問題を解いてからの方が良いと思います。
    wave-decayp.c
    #include<stdio.h>
    #include<limits.h>
    #include<math.h>
    
    int main(void){
    	FILE *fp;
    
    	/***文字列"RIFF"の宣言・設定***/
    	char s_riff[/***ここに絶対何か書く***/];
    
    	/***文字列"WAVE"の宣言・設定***/
    	char s_wave[/***ここに絶対何か書く***/];
    	/***ファイルサイズWholeSizeの宣言***/
    	int WholeSize;
    
    	/***文字列"fmt "の宣言・設定***/
    	char s_fmt[/***ここに絶対何か書く***/];
    	/***fmtチャンクサイズの宣言***/
    	int FmtChunkSize;
    	/***↓フォーマットID:FmtIDを宣言・設定***/
    	short FmtId;
    	/***↓チャネル数Channelを宣言・設定***/
    	short Channel;
    	/***↓サンプリングレートSamplingRateを宣言・設定***/
    	int SamplingRate;
    	/***↓データ速度DataVelocityを宣言***/
    	int DataVelocity;
    	/***↓ブロックサイズBlockSizeを宣言・設定***/
    	short BlockSize;
    	/***↓サンプル単位ビット数を設定***/
    	short Bps;
    
    	/***文字列"data"の設定***/
    	char s_data[/***ここに絶対何か書く***/];
    	/***↓dataチャンクサイズを宣言***/
    	int DataChunkSize;
    	/***↓波形データ格納用領域を指すポインタ変数を宣言***/
    	short *wave;
    
    	int i, chk;
    
    	/***入力ファイルのオープン***/
    	/***ここに絶対何か書く***/
    
    	/***↓s_riffへの入力***/
    	/***ここに絶対何か書く***/
    
    	/***↓s_riffの末尾要素に終端文字の設定***/
    	/***ここに絶対何か書く***/
    
    	/***↓s_riffと"RIFF"が一致しなければプログラム終了***/
    	/***ここに何か書く***/
    
    	/***↓WholeSizeへの入力***/
    	/***ここに絶対何か書く***/
    
    	/***↓s_waveへの入力***/
    	/***ここに絶対何か書く***/
    
    	/***↓s_waveの末尾要素に終端文字の設定***/
    	/***ここに絶対何か書く***/
    
    	/***↓s_waveと"WAVE"が一致しなければプログラム終了***/
    	/***ここに何か書く***/
    	
    
    	/***ここからfmtチャンクの入力***/
    	
    	/***↓s_fmtへの入力***/
    	/***ここに絶対何か書く***/
    
    	/***↓s_fmtの末尾要素に終端文字の設定***/
    	/***ここに絶対何か書く***/
    
    	/***↓s_fmtと"fmt "が一致しなければプログラム終了***/
    	/***ここに何か書く***/
    	
    	/***↓FmtChunkSizeへの入力***/
    	/***ここに絶対何か書く***/
    
    	/***↓FmtChunkSizeが適切でなければプログラム終了***/
    	/***ここに何か書く***/
    
    	/***↓FmtIdへの入力***/
    	/***ここに絶対何か書く***/
    
    	/***↓FmtIdが適切でなければプログラム終了***/
    	/***ここに何か書く***/
    
    	/***↓Channelへの入力***/
    	/***ここに絶対何か書く***/
    
    	/***↓Channelが適切でなければプログラム終了***/
    	/***ここに何か書く***/
    
    	/***↓SamplingRateへの入力***/
    	/***ここに絶対何か書く***/
    
    	/***↓DataVelocityへの入力***/
    	/***ここに絶対何か書く***/
    
    	/***↓BlockSizeへの入力***/
    	/***ここに絶対何か書く***/
    
    	/***↓Bpsへの入力***/
    	/***ここに絶対何か書く***/
    
    	/***↓Bpsが16でなければプログラム終了***/
    	/***ここに何か書く***/
    
    	/***↓DetaVelocityが適切でなければプログラム終了***/
    	/***ここに何か書く***/
    
    	/***↓BlockSizeが適切でなければプログラム終了***/
    	/***ここに何か書く***/
    
    
    	/***ここまでfmtチャンクの入力***/
    	/***ここからdataチャンクの入力***/
    	
    	/***↓s_dataへの入力***/
    	/***ここに絶対何か書く***/
    
    	/***↓s_dataの末尾要素に終端文字の設定***/
    	/***ここに絶対何か書く***/
    
    	/***↓s_dataと"data"が一致しなければプログラム終了***/
    	/***ここに何か書く***/
    
    	/***↓DataChunkSizeへの入力***/
    	/***ここに絶対何か書く***/
    
    	/***↓WholeSizeが適切でなければプログラムの終了***/
    	/***ここに何か書く***/
    
    	/***↓waveの領域確保***/
    	/***ここに絶対何か書く***/
    
    	/***↓waveへの入力***/
    	/***ここに絶対何か書く***/
    
    	/***ここまでdataチャンクのファイル出力***/
    	/***↑ファイル入力の終了***/
    	fclose(fp);
    
    	/***波形データの加工***/
    	/***ここに何か書く***/
    
    	/***出力ファイルのオープン***/
    	/***ここに絶対何か書く***/
    
    	/***↓"RIFF"のファイル出力***/
    	/***ここに絶対何か書く***/
    
    	/***↓WholeSizeのファイル出力***/
    	/***ここに絶対何か書く***/
    
    	/***↓"WAVE"のファイル出力***/
    	/***ここに絶対何か書く***/
    
    	/***ここからfmtチャンクのファイル出力***/
    	
    	/***↓"fmt "のファイル出力***/
    	/***ここに絶対何か書く***/
    
    	/***↓fmtチャンクサイズFmtChunkSizeのファイル出力***/
    	/***ここに絶対何か書く***/
    
    	/***↓フォーマットID:FmtIdのファイル出力***/
    	/***ここに絶対何か書く***/
    
    	/***↓チャネル数Channelのファイル出力***/
    	/***ここに絶対何か書く***/
    
    	/***↓サンプリングレートSamplingRateのファイル出力***/
    	/***ここに絶対何か書く***/
    
    	/***↓データ速度DataVelocityのファイル出力***/
    	/***ここに絶対何か書く***/
    
    
    	/***↓ブロックサイズBlockSizeのファイル出力***/
    	/***ここに絶対何か書く***/
    
    	/***↓サンプル単位ビット数Bpsのファイル出力***/
    	/***ここに絶対何か書く***/
    
    	/***ここまでfmtチャンクのファイル出力***/
    	/***ここからdataチャンクのファイル出力***/
    	
    	/***↓"data"のファイル出力***/
    	/***ここに絶対何か書く***/
    
    	/***↓dataチャンクサイズDataChunkSizeのファイル出力***/
    	/***ここに絶対何か書く***/
    
    	/***↓波形データwaveのファイル出力***/
    	/***ここに絶対何か書く***/
    
    	/***ここまでdataチャンクのファイル出力***/
    	
    	fclose(fp);
    
    	return 0;
    }
    

    wave-decay.c
    #include<stdio.h>
    #include<limits.h>
    #include<math.h>
    
    int main(void){
    	FILE *fp;
    
    	/***文字列"RIFF"の宣言・設定***/
    	char s_riff[5];
    
    	/***文字列"WAVE"の宣言・設定***/
    	char s_wave[5];
    	/***ファイルサイズWholeSizeの宣言***/
    	int WholeSize;
    
    	/***文字列"fmt "の宣言・設定***/
    	char s_fmt[5];
    	/***fmtチャンクサイズの宣言***/
    	int FmtChunkSize;
    	/***↓フォーマットID:FmtIDを宣言・設定***/
    	short FmtId;
    	/***↓チャネル数Channelを宣言・設定***/
    	short Channel;
    	/***↓サンプリングレートSamplingRateを宣言・設定***/
    	int SamplingRate;
    	/***↓データ速度DataVelocityを宣言***/
    	int DataVelocity;
    	/***↓ブロックサイズBlockSizeを宣言・設定***/
    	short BlockSize;
    	/***↓サンプル単位ビット数を設定***/
    	short Bps;
    
    	/***文字列"data"の設定***/
    	char s_data[5];
    	/***↓dataチャンクサイズを宣言***/
    	int DataChunkSize;
    	/***↓波形データ格納用領域を指すポインタ変数waveを宣言***/
    	short *wave;
    
    	int i, chk;
    
    	/***入力ファイルのオープン***/
    	fp=fopen("pcm-8000Hz-1c-2byte-1000Hz-2sec.wav", "rb");
    	if(fp==NULL){
    		printf("Cannot open File for input\n");
    		exit(1);
    	}
    
    	/***↓s_riffへの入力***/
    	chk=fread(s_riff, sizeof(s_riff[0]), 4, fp);
    	if(chk<4){
    		printf("Read Error for s_riff\n");
    		exit(1);
    	}
    	/***↓s_riffの末尾要素に終端文字の設定***/
    	s_riff[4]='\0';
    	/***↓s_riffと"RIFF"が一致しなければプログラム終了***/
    	if(strcmp(s_riff, "RIFF")!=0){
    		printf("Not \"RIFF\" but %s\n", s_riff);
    		exit(1);
    	}
    
    	/***↓WholeSizeへの入力***/
    	chk=fread(&WholeSize, sizeof(WholeSize), 1, fp);
    	if(chk<1){
    		printf("Write Error for WholeSize\n");
    		exit(1);
    	}
    
    	/***↓s_waveへの入力***/
    	chk=fread(s_wave, sizeof(s_wave[0]), 4, fp);
    	if(chk<4){
    		printf("Read Error for s_wave\n");
    		exit(1);
    	}
    	/***↓s_waveの末尾要素に終端文字の設定***/
    	s_wave[4]='\0';
    	/***↓s_waveと"WAVE"が一致しなければプログラム終了***/
    	if(strcmp(s_wave, "WAVE")!=0){
    		printf("Not \"WAVE\" but %s\n", s_wave);
    		exit(1);
    	}
    	
    
    	/***ここからfmtチャンクの入力***/
    	
    	/***↓s_fmtへの入力***/
    	chk=fread(s_fmt, sizeof(s_fmt[0]), 4, fp);
    	if(chk<4){
    		printf("Read Error for s_fmt\n");
    		exit(1);
    	}
    	/***↓s_fmtの末尾要素に終端文字の設定***/
    	s_fmt[4]='\0';
    	/***↓s_fmtと"fmt "が一致しなければプログラム終了***/
    	if(strcmp(s_fmt, "fmt ")!=0){
    		printf("Not \"fmt \" but %s\n", s_fmt);
    		exit(1);
    	}
    	
    
    	/***↓FmtChunkSizeへの入力***/
    	chk=fread(&FmtChunkSize, sizeof(FmtChunkSize), 1, fp);
    	if(chk<1){
    		printf("Write Error for FmtChunkSize\n");
    		exit(1);
    	}
    	/***↓FmtChunkSizeが適切でなければプログラム終了***/
    	if(FmtChunkSize!=
    		sizeof(FmtId)+
    		sizeof(Channel)+
    		sizeof(SamplingRate)+
    		sizeof(DataVelocity)+
    		sizeof(BlockSize)+
    		sizeof(Bps)
    		){
    		printf("FmtChunkSize is not %d but %d\n",
    			sizeof(FmtId)+
    			sizeof(Channel)+
    			sizeof(SamplingRate)+
    			sizeof(DataVelocity)+
    			sizeof(BlockSize)+
    			sizeof(Bps),
    			FmtChunkSize);
    		exit(1);
    	}
    
    	/***↓FmtIdへの入力***/
    	chk=fread(&FmtId, sizeof(FmtId), 1, fp);
    	if(chk<1){
    		printf("Write Error for FmtId\n");
    		exit(1);
    	}
    	/***↓FmtIdが適切でなければプログラム終了***/
    	if(FmtId!=1){
    		printf("FmtId is not 1 but %d\n", FmtId);
    		exit(1);
    	}
    
    	/***↓Channelへの入力***/
    	chk=fread(&Channel, sizeof(Channel), 1, fp);
    	if(chk<1){
    		printf("Write Error for Channel\n");
    		exit(1);
    	}
    	/***↓Channelが適切でなければプログラム終了***/
    	if(Channel!=1){
    		printf("Channel is not 1 but %d\n", Channel);
    		exit(1);
    	}
    
    	/***↓SamplingRateへの入力***/
    	chk=fread(&SamplingRate, sizeof(SamplingRate), 1, fp);
    	if(chk<1){
    		printf("Write Error for SamplingRate\n");
    		exit(1);
    	}
    
    	/***↓DataVelocityへの入力***/
    	chk=fread(&DataVelocity, sizeof(DataVelocity), 1, fp);
    	if(chk<1){
    		printf("Write Error for DataVelocity\n");
    		exit(1);
    	}
    
    
    	/***↓BlockSizeへの入力***/
    	chk=fread(&BlockSize, sizeof(BlockSize), 1, fp);
    	if(chk<1){
    		printf("Write Error for BlockSize\n");
    		exit(1);
    	}
    
    	/***↓Bpsへの入力***/
    	chk=fread(&Bps, sizeof(Bps), 1, fp);
    	if(chk<1){
    		printf("Write Error for Bps\n");
    		exit(1);
    	}
    	/***↓Bpsが16でなければプログラム終了***/
    	if(Bps!=16){
    		printf("Bps is not 16 but %d\n", Bps);
    		exit(1);
    	}
    	/***↓DetaVelocityが適切でなければプログラム終了***/
    	if(DataVelocity!=SamplingRate*Bps/8*Channel){
    		printf("DataVeclocity Unmatched\n DataVelocity:%d, SamplingRate:%d, Bps:%d, Channel:%d\n",
    			DataVelocity, SamplingRate, Bps, Channel);
    		exit(1);
    	}
    	/***↓BlockSizeが適切でなければプログラム終了***/
    	if(BlockSize!=Bps/8*Channel){
    		printf("BlockSize Unmatched\n BlockSize:%d, Bps:%d, Channel:%d\n",
    			BlockSize, Bps, Channel);
    		exit(1);
    	}
    
    
    	/***ここまでfmtチャンクの入力***/
    	/***ここからdataチャンクの入力***/
    	
    	/***↓s_dataへの入力***/
    	chk=fread(s_data, sizeof(s_data[0]), 4, fp);
    	if(chk<4){
    		printf("Read Error for s_data\n");
    		exit(1);
    	}
    	/***↓s_dataの末尾要素に終端文字の設定***/
    	s_data[4]='\0';
    	/***↓s_dataと"data"が一致しなければプログラム終了***/
    	if(strcmp(s_data, "data")!=0){
    		printf("Not \"data\" but %s\n", s_data);
    		exit(1);
    	}
    
    	/***↓DataChunkSizeへの入力***/
    	chk=fread(&DataChunkSize, sizeof(DataChunkSize), 1, fp);
    	if(chk<1){
    		printf("Write Error for DataChunkSize\n");
    		exit(1);
    	}
    	/***↓WholeSizeが適切でなければプログラムの終了***/
    	if(WholeSize!=strlen("WAVE")
    		+strlen("fmt ")
    		+sizeof(FmtChunkSize)
    		+FmtChunkSize
    		+strlen("data")
    		+sizeof(DataChunkSize)
    		+DataChunkSize){
    		printf("WholeSize Unmatced\n WholeSize:%d, FmtChunkSize:%d, DataChunkSize:%d\n",
    			WholeSize, FmtChunkSize, DataChunkSize);
    		exit(1);
    	}
    
    	/***↓waveの領域確保***/
    	wave=(short *)malloc(sizeof(short)*DataChunkSize/sizeof(short));
    	if(wave==NULL){
    		printf("Out of Memory\n");
    		exit(1);
    	}
    
    	/***↓waveへの入力***/
    	chk=fread(wave, sizeof(wave[0]), DataChunkSize/sizeof(wave[0]), fp);
    	if(chk<DataChunkSize/sizeof(wave[0])){
    		printf("Read Error for wave[%d]\n", i);
    		exit(1);
    	}
    
    	/***ここまでdataチャンクのファイル出力***/
    	/***↑ファイル入力の終了***/
    	fclose(fp);
    
    	/***波形データの加工***/
    	for(i=0;i<DataChunkSize/sizeof(wave[0]);i++){
    		wave[i]=(short)(((double)wave[i])*
    			(1.0-i/(((double)(DataChunkSize/sizeof(wave[0])))-1.0))
    		);
    	}
    
    	/***出力ファイルのオープン***/
    	fp=fopen("pcm-8000Hz-1c-2byte-1000Hz-2sec-decay.wav", "wb");
    	if(fp==NULL){
    		printf("Cannot open File for output\n");
    		exit(1);
    	}
    
    	/***↓"RIFF"のファイル出力***/
    	chk=fwrite(s_riff, sizeof(s_riff[0]), strlen(s_riff), fp);
    	if(chk<strlen(s_riff)){
    		printf("Write Error for s_riff\n");
    		exit(1);
    	}
    
    	/***↓WholeSizeのファイル出力***/
    	chk=fwrite(&WholeSize, sizeof(WholeSize), 1, fp);
    	if(chk<1){
    		printf("Write Error for WholeSize\n");
    		exit(1);
    	}
    
    	/***↓"WAVE"のファイル出力***/
    	chk=fwrite(s_wave, sizeof(s_wave[0]), strlen(s_wave), fp);
    	if(chk<strlen(s_wave)){
    		printf("Write Error for s_wave\n");
    		exit(1);
    	}
    
    	/***ここからfmtチャンクのファイル出力***/
    	
    	/***↓"fmt "のファイル出力***/
    	chk=fwrite(s_fmt, sizeof(s_fmt[0]), strlen(s_fmt), fp);
    	if(chk<strlen(s_fmt)){
    		printf("Write Error for s_fmt\n");
    		exit(1);
    	}
    
    	/***↓fmtチャンクサイズFmtChunkSizeのファイル出力***/
    	chk=fwrite(&FmtChunkSize, sizeof(FmtChunkSize), 1, fp);
    	if(chk<1){
    		printf("Write Error for FmtChunkSize\n");
    		exit(1);
    	}
    
    	/***↓フォーマットID:FmtIdのファイル出力***/
    	chk=fwrite(&FmtId, sizeof(FmtId), 1, fp);
    	if(chk<1){
    		printf("Write Error for FmtId\n");
    		exit(1);
    	}
    
    	/***↓チャネル数Channelのファイル出力***/
    	chk=fwrite(&Channel, sizeof(Channel), 1, fp);
    	if(chk<1){
    		printf("Write Error for Channel\n");
    		exit(1);
    	}
    
    	/***↓サンプリングレートSamplingRateのファイル出力***/
    	chk=fwrite(&SamplingRate, sizeof(SamplingRate), 1, fp);
    	if(chk<1){
    		printf("Write Error for SamplingRate\n");
    		exit(1);
    	}
    
    	/***↓データ速度DataVelocityのファイル出力***/
    	chk=fwrite(&DataVelocity, sizeof(DataVelocity), 1, fp);
    	if(chk<1){
    		printf("Write Error for DataVelocity\n");
    		exit(1);
    	}
    
    
    	/***↓ブロックサイズBlockSizeのファイル出力***/
    	chk=fwrite(&BlockSize, sizeof(BlockSize), 1, fp);
    	if(chk<1){
    		printf("Write Error for BlockSize\n");
    		exit(1);
    	}
    
    	/***↓サンプル単位ビット数Bpsのファイル出力***/
    	chk=fwrite(&Bps, sizeof(Bps), 1, fp);
    	if(chk<1){
    		printf("Write Error for Bps\n");
    		exit(1);
    	}
    
    	/***ここまでfmtチャンクのファイル出力***/
    	/***ここからdataチャンクのファイル出力***/
    	
    	/***↓"data"のファイル出力***/
    	chk=fwrite(s_data, sizeof(s_data[0]), strlen(s_data), fp);
    	if(chk<strlen(s_data)){
    		printf("Write Error for s_data\n");
    		exit(1);
    	}
    
    	/***↓dataチャンクサイズDataChunkSizeのファイル出力***/
    	chk=fwrite(&DataChunkSize, sizeof(DataChunkSize), 1, fp);
    	if(chk<1){
    		printf("Write Error for DataChunkSize\n");
    		exit(1);
    	}
    
    	/***↓波形データwaveのファイル出力***/
    	chk=fwrite(wave, sizeof(wave[0]), DataChunkSize/sizeof(wave[0]), fp);
    	if(chk<sizeof(wave)/sizeof(wave[0])){
    		printf("Write Error for wave[%d]\n", i);
    		exit(1);
    	}
    
    	/***ここまでdataチャンクのファイル出力***/
    	
    	fclose(fp);
    
    	return 0;
    }
    
  4. 上の問を解くための考察として、 次の「あ」から「く」に適切に埋めてください。
    1. まず入力ファイルから各データを入力して対応する変数に格納していきます。
      1. 文字列"RIFF"が格納されるはずの文字型配列をs_riffとします。 s_riffの型はcharで、 その要素数は、文字列"RIFF"の文字数と終端文字分を合わせた5にします。
      2. ファイルサイズから8を差し引いた大きさが格納されるはずの変数をWholeSizeとします。 これを4バイトで格納するのでint型で宣言します。
      3. 文字列"WAVE"が格納されるはずの文字型配列をs_waveとします。 s_waveの型はcharで、 その要素数は、文字列"WAVE"の文字数と終端文字分を合わせた5にします。

      ここからfmtチャンクの入力に必要な変数を宣言していきます。

      1. まず文字列"fmt "が格納されるはずの文字型配列をs_fmtとします。 s_fmtの型はcharで、 その要素数は、文字列"fmt "の文字数と終端文字分を合わせた5にします。
      2. 次にfmtチャンクサイズからチャンク名("fmt ")とチャンクサイズを格納する分を差し引いた大きさが格納されるはずの変数をFmtChunkSizeとします。 これを4バイトで格納するのでint型で宣言します。
      3. 次にフォーマットIDが格納されるはずの変数をFmtIdとします。 これを2バイトで格納するのでshort型で宣言します。
      4. 次にチャネル数が格納されるはずの変数をChannelとします。 これを2バイトで格納するのでshort型で宣言します。
      5. 次にサンプリングレートが格納されるはずの変数をSamplingRateとします。 これを4バイトで格納するのでint型で宣言します。
      6. 次にデータ速度が格納されるはずの変数をDataVelocityとします。 これを4バイトで格納するのでint型で宣言します。
      7. 次にブロックサイズが格納されるはずの変数をBlockSizeとします。 これを2バイトで格納するのでshort型で宣言します。
      8. 次に単位ビット数が格納されるはずの変数をBpsとします。 これを2バイトで格納するのでshort型で宣言します。
      9. 場合によっては入力対象のWAVファイルに拡張部分が格納されていて これを入力しなければならないこともありますが、 本課題では無視します。
      これでfmtチャンクの入力に必要な変数の宣言が終りました。

      場合によっては入力対象のWAVファイルにfactチャンクが格納されていて これを入力しなければならないこともありますが、 本課題では無視します。

      ここからdataチャンクの入力に必要な変数の宣言を行います。

      1. まず文字列"data"が格納されるはずの文字型配列をs_dataとします。 s_dataの型はcharで、 その要素数は、文字列"data"の文字数と終端文字分を合わせた5にします。
      2. dataチャンクサイズからチャンク名("data")分とdataチャンクサイズを格納する分を差し引いたものが格納されるはずの変数をDataChunkSizeとします。 これを4バイトで格納するのでint型で宣言します。
      3. 波形データを格納するための領域を指すポインタ変数名をWaveDataとします。 本課題では単位ビット数が16なのでshort型へのポインタ変数として宣言します。
      これでdataチャンクの入力に必要な変数の宣言が終りました。

      場合によっては入力対象のWAVファイルにLISTチャンクが格納されていて これを入力しなければならないこともありますが、 本課題では無視します。

      これで一通り、プログラミングに必要な変数の宣言が終りました。 その他に必要な変数は適宜、宣言してください。

      入力ファイルをオープンした後に、 各データをファイルから入力していきます。

      1. まず、ファイルから4文字を入力してs_riffに格納します。 このときfread関数の 第1引数はs_riff、 第2引数は1文字分の大きさsizeof(s_riff[0])、 第3引数は文字数4、 第4引数はfpです。 念のためfread関数の戻り値を用いて 読み込みバイト数を確認してください。
        • また、配列s_riffの5番目の要素を終端文字に設定します。
        • そして、文字型配列s_riffに格納された文字列と 文字列"RIFF"が一致していなければ その旨のメッセージを画面表示してプログラムを終了します。
      2. 次にファイルから4バイト入力してWholeSizeに格納します。 このときfread関数の 第1引数は&WholeSize、 第2引数はデータの大きさsizeof(WholeSize)、 第3引数はデータの個数1、 第4引数はfpです。 念のためfread関数の戻り値を用いて 読み込みバイト数を確認してください。
      3. ここからWAVEチャンクを入力していきます。
        1. ファイルから4文字を入力してs_waveに格納します。 このときfread関数の 第1引数はs_wave、 第2引数は1文字分の大きさsizeof(s_wave[0])、 第3引数は文字数4、 第4引数はfpです。 念のためfread関数の戻り値を用いて 読み込みバイト数を確認してください。
          • また、配列s_waveの5番目の要素を終端文字に設定します。
          • そして、文字型配列s_waveに格納された文字列と 文字列"WAVE"が一致していなければ その旨のメッセージを画面表示してプログラムを終了します。
        2. ここからfmtチャンクを入力していきます。
          1. 次に、ファイルから4文字を入力してs_fmtに格納します。 このときfread関数の 第1引数はs_fmt、 第2引数は1文字分の大きさsizeof(s_fmt[0])、 第3引数は文字数4、 第4引数はfpです。 念のためfread関数の戻り値を用いて 読み込みバイト数を確認してください。
            • また、配列s_fmtの5番目の要素を終端文字に設定します。
            • そして、文字型配列s_fmtに格納された文字列と 文字列"fmt "が一致していなければ その旨のメッセージを画面表示してプログラムを終了します。
          2. 次に4バイト入力してFmtChunkSizeに格納します。 このときfread関数の 第1引数は&FmtChunkSize、 第2引数はデータの大きさsizeof(FmtChunkSIze)、 第3引数はデータの個数1、 第4引数はfpです。 念のためfread関数の戻り値を用いて 読み込みバイト数を確認してください。
            • 本課題では、fmtチャンクの拡張部分がないと仮定しているので、 fmtチャンクサイズは24バイトのはずです。 よって、変数FmtChunkSizeには、 24バイトから文字列"fmt "の文字数分4を差し引いた20が格納されているはずです。 そこで、 もし、FmtChunkSizeが20でなかったら、 その旨のメッセージを画面表示してプログラムを終了します。
          3. 次に2バイト入力してFmtIdに格納します。 このときfread関数の 第1引数は&FmtId、 第2引数はデータの大きさsizeof(FmtId)、 第3引数はデータの個数1、 第4引数はfpです。 念のためfread関数の戻り値を用いて 読み込みバイト数を確認してください。
            • 本課題ではリニアPCMを仮定しているので、 変数FmtIdには1が格納されているはずです。 そこで、 もし、FmtIdが1でなかったら、 その旨のメッセージを画面表示してプログラムを終了します。
          4. 次に2バイト入力してChannelに格納します。 このときfread関数の 第1引数は&Channel、 第2引数はデータの大きさsizeof(Channel)、 第3引数はデータの個数1、 第4引数はfpです。 念のためfread関数の戻り値を用いて 読み込みバイト数を確認してください。
              本課題では、モノラル音声のみを仮定しているので、 変数Channelには1が格納されているはずです。 そこで、 もし、Channelが1でなかったら、 その旨のメッセージを画面表示してプログラムを終了します。
          5. 次に4バイト入力してSamplingRateに格納します。 このときfread関数の 第1引数は&SamplingRate、 第2引数はデータの大きさsizeof(SamplingRate)、 第3引数はデータの個数1、 第4引数はfpです。 念のためfread関数の戻り値を用いて 読み込みバイト数を確認してください。
          6. 次に4バイト入力してDataVelocityに格納します。 このときfread関数の 第1引数は&DataVelocity、 第2引数はデータの大きさsizeof(DataVelocity)、 第3引数はデータの個数1、 第4引数はfpです。 念のためfread関数の戻り値を用いて 読み込みバイト数を確認してください。
          7. 次に2バイト入力してBlockSizeに格納します。 このときfread関数の 第1引数は&BlockSize、 第2引数はデータの大きさsizeof(BlockSize)、 第3引数はデータの個数1、 第4引数はfpです。 念のためfread関数の戻り値を用いて 読み込みバイト数を確認してください。
          8. 次に2バイト入力してBpsに格納します。 このときfread関数の 第1引数は&Bps、 第2引数はデータの大きさsizeof(Bps)、 第3引数はデータの個数1、 第4引数はfpです。 念のためfread関数の戻り値を用いて 読み込みバイト数を確認してください。
            • 本課題では単位ビット数を16ビットと仮定しています。 そこで、 もし、Bpsが16でなかったら、 その旨のメッセージを画面表示してプログラムを終了します。
            • また、データ速度、サンプリングレート、単位ビット数、チャネル数には、 データ速度=サンプリングレート×単位ビット数÷8×チャネル数の関係が成立していなければなりません。 そこで、 もし、変数DetaVelocitySamplingrate*Bps/8*Channelと等しくない場合には その旨のメッセージを画面表示してプログラムを終了します。
            • さらに、 ブロックサイズ、単位ビット数、チャネル数には、 ブロックサイズ=単位ビット数÷8×チャネル数の関係が成立していなければなりません。 そこで、変数BlockSizeBps/8*Channelと等しくない場合には その旨のメッセージを画面表示してプログラムを終了します。
        3. ここからdataチャンクを入力していきます。
          1. まず、4文字入力して文字型配列s_dataに格納します。 このときfread関数の 第1引数はs_data、 第2引数は1文字分の大きさsizeof(s_data[0])、 第3引数は文字数4、 第4引数はfpです。 念のためfread関数の戻り値を用いて 書き込みバイト数を確認してください。
            • また、配列s_dataの5番目の要素を終端文字に設定します。
            • そして、文字型配列s_dataに格納された文字列と 文字列"data"が一致していなければ その旨のメッセージを画面表示してプログラムを終了します。
          2. 次に4バイト入力してDataChunkSizeに格納します。 このときfread関数の 第1引数は&DataChunkSize、 第2引数はデータの大きさsizeof(DataChunkSize)、 第3引数はデータの個数1、 第4引数はfpです。 念のためfread関数の戻り値を用いて 読み込みバイト数を確認してください。
            • DataChunkSizeは 波形データを格納するためのバイト数を表すことになります。 波形データの1要素はshort型なので 波形データを格納していく領域はshort型にして DataChunkSize/sizeof(short)個になります。 ここで、波形データを格納していく領域を確保して、 その先頭アドレスをWaveDataに設定します。
            • もし、波形データ以降に格納されているかも知れないLISTチャンクがないならば、 この時点でファイルサイズが判明し、 それは、 文字列"RIFF"の文字数と、 変数WholeSizeの大きさと、 文字列"WAVE"の文字数と、 文字列"fmt "の文字数と、 変数FmtChunkSizeの大きさと、 変数FmtChunkSizeに格納されている値と、 文字列"data"の文字数と、 変数DataChunkSizeの大きさと、 変数DataChunkSizeに格納されている値との総和になります。 これらの総和から 文字列"RIFF"の文字数の分と 変数WholeSizeの大きさの分を差し引いたものが 変数WholeSizeに格納されている値と一致しなければなりません。 そこで、 変数WholeSizeに格納されている値が、 文字列"WAVE"の文字数と 文字列"fmt "の文字数と 変数FmtChunkSizeの大きさと 変数FmtChunkSizeに格納されている値と 文字列"data"の文字数と 変数DataChunkSizeの大きさと 変数DataChunkSizeに格納されている値との総和に等しくない場合には、 その旨のメッセージを画面表示して プログラムを終了します。
          3. 次に、 short型DatachunkSize個分入力して WaveDataの指す領域に格納します。 このときfread関数の 第1引数はWaveData、 第2引数はデータの大きさsizeof(WaveData[0])、 第3引数はデータの個数DataChunkSize/sizeof(WaveData[0])、 第4引数はfpです。 念のためfread関数の戻り値を用いて 読み込みバイト数を確認してください。

        これでファイル入力が終了したのでファイルをクローズします。

    2. ここで、波形データを加工します。 詳細は前回のレポート課題を参考にしてください。
    3. ここからファイル出力を始めます。 詳細は前回のレポート課題を参考にしてください。

以下は、皆さんの幾つかの考察・感想に対するコメントです。 ただし今回は、レポート課題に直接関連することのみに限定しています。
雛形を用いずに完成させた学生はいますか?
提出されたプログラムを見るだけでは雛型を用いたか否かを判断するのは難しいですね。 あくまでも感覚的でですが、雛型を用いずに完成させた方はいないと思います。
セグメントエラーになやまされています。
セグメントエラーはメモリアクセスに関わるエラーなので、 配列の添字ミスなどに当たりをつけながら、 GDBで確認するのが良いと思います。 また、各データ読み込み(もしくは書き込み)毎に変数を画面表示したり、 一旦そこでreturn 0;でプログラムを終了させてしまうことで、 エラーの発生箇所を特定できることもあります。

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