short
型の配列に格納し、
そのi
番目の要素にを乗じて、
バイナリファイルshort1000-1new.datに出力するプログラムを作成して下さい。
正しく計算するために、係数中の整数定数には小数点を用い、
整数変数を一旦double
型に変換してから計算し、
あらためて配列の要素に代入する際にshort
型に変換することに注意してください。
report12-1.c |
---|
#include<stdio.h> #include<stdlib.h> int main(void){ FILE *fp; int chk, i; short a[1000]; fp=fopen("short1000-1.dat", "rb"); if(fp==NULL){ printf("File Can't Open\n"); exit(1); } chk=fread(a, sizeof(a[0]), sizeof(a)/sizeof(a[0]), fp); if(chk<1000){ printf("Read Error\n"); exit(1); } fclose(fp); for(i=0;i<1000;i++){ a[i]=(2.0*((double)i)+0.8)*a[i]; } fp=fopen("short1000-1new.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<1000){ printf("Write Error\n"); exit(1); } fclose(fp); return 0; } |
sox -V -r 8000 -s -w -c 1 sample-decay.raw -t ossdsp /dev/dsp0 |
report12-3.c |
---|
#include<stdio.h> #include<stdlib.h> int main(void){ short a[16000]; int chk, i; FILE *fp; fp=fopen("pcm-8000Hz-1c-2byte-1000Hz-2sec.raw", "rb"); chk=fread(a, sizeof(a[0]), sizeof(a)/sizeof(a[0]), fp); if(chk<sizeof(a)/sizeof(a[0])){ printf("Read Error\n"); exit(1); } fclose(fp); for(i=0;i<16000;i++){ a[i]=(short)(((double)a[i])*(1.0-((double)i)/15999.0)); } fp=fopen("pcm-8000Hz-1c-2byte-1000Hz-2sec-decay.raw", "wb"); chk=fwrite(a, sizeof(a[0]), sizeof(a)/sizeof(a[0]), fp); if(chk<sizeof(a)/sizeof(a[0])){ printf("Write Error\n"); exit(1); } fclose(fp); /***画面表示確認用 for(i=0;i<16000;i++){ printf("%d\n", a[i]); } ***/ return 0; } |
ファイルpcm-8000Hz-1c-2byte-1000Hz-2sec.rawには、
サンプリングレート8000Hz、モノラル、16ビット符号つきデータとして、2秒間の波形データが格納されているので、
これを入力するために、short型16000個の要素を持つ配列a
を用意して、
fread
関数を用いて配列a
に入力します。
音量を減衰するには、配列の各要素を1以下の小数で乗じます。 線形に減衰するには、先頭要素については1倍、末尾要素については0倍し、 その間の要素については0から1までの適切な小数で乗じます。 すなわち、0番目の要素に乗じる係数が1.0、 対象データの要素数は16000なので、15999番目の要素に乗じる係数が0.0、 したがって番目の要素に乗じる係数はになります。
a[i]*=1.0-((double)i)/15999.0; |
for(i=0;i<16000;i++){ a[i]*=(short)(1.0-(double)(i)/16000); } |
short
型に変換すると1未満の係数はすべて0になってしまいます。
よって乗算代入演算子を用いる場合には右辺をshort
型に変換してはいけません。
暗黙の型変換において
short
型とdouble
型の乗算結果がdouble
型になることと、
double
型をshort
型に代入すると小数部分が打ち切られることを利用することになります。
ただし、本科目では暗黙の型変換について詳しく学習していないのでこの方法を公式に勧めることはできません。
for(i=0;i<DATASIZE;i++){ a[i]=(short)(32767.0*sin((2000.0*M_PI)*(1/8000.0)*((double)(i)))); } |
for(i=0;i<DATASIZE;i++) { a[i]=(short)((a[i])*((((double)(DATASIZE-1.0))-((double)(i)))/((double)(DATASIZE-1.0)))); } |
a[i]
をdouble
に変換することとDATASIZE
をdouble
に変換するのですが。
int
型16000個分入力しようとしたら8000個入力したところでデータがなくなってリードエラーが起きたのだと思います。