short型の配列に格納し、
そのi番目の要素に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 |
| 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個入力したところでデータがなくなってリードエラーが起きたのだと思います。