8bitデータの調整方法

このQ&Aのポイント
  • VS2003.NET/C++でプログラミングをしている場合、8bitのwaveファイルで音声データを取得し、フェードを掛けようとする際、16bitとは異なり、1byteに左チャネル、2byte目に右チャンネルが格納されているため、音量調整が上手くいかない。
  • 16bitデータの場合、2byteずつ確保し、音量調整を行うが、8bitデータの場合は、4byteずつ確保し、音量調整を行う必要がある。
  • 8bitデータの音量調整方法は、まず1byte目から128を引いてから、音量調整倍率をかけ、さらに128を足す。その後、加工済みデータを保存する。
回答を見る
  • ベストアンサー

waveファイルの8bitデータの調整

VS2003.NET/C++でプログラミングをしています。 今、WAVEファイルで音声データを取って、フェードを掛けようと思うのですが、8bitだと上手くいきません。  16bitの場合は、2byte分読み込み、それから小数で割っているんですが、8bitの場合、1byteに左チャネル、2byte目には右チャンネルといった形で格納されているはずなんですがそのようにしても上手くいきません。  上手くいった16bitデータの音量調整を下記に載せておきます。 8bitにするにはどうしたらいいでしょうか? int nMeter; <- 音量を100分割で表す int nSize; <- データのサイズ LPBYTE lpData1; <- 相手の音声 LPBYTE lpData2; <- 音声を加工 // サイズ分を加工 for( int i = 0; i < nSize; i+=2 ) { // 16bit なので 2BYTEずつ確保 char n1 = (char)( lpData1[ i + 0 ] ); char n2 = (char)( lpData1[ i + 1 ] ); // nMeter で音量調整(倍率をかける) int n = (int)( (float)( ( n2 << 8 ) | ( n1 & 0xFF ) ) * (float)( nMeter / 100.0f ) ); // 加工済みデータを保存 lpData2[ i + 0 ] = ( n & 0x00FF ) >> 0; lpData2[ i + 1 ] = ( n & 0xFF00 ) >> 8; } 上手くいってない8bit版は次の通りです int nMeter; <- 音量を100分割で表す int nSize; <- データのサイズ LPBYTE lpData1; <- 相手の音声 LPBYTE lpData2; <- 音声を加工 // サイズ分を加工 for( int i = 0; i < nSize; i+=4 ) { // 16bit なので 2BYTEずつ確保 char n1 = (char)( lpData1[ i + 0 ] ); char n2 = (char)( lpData1[ i + 1 ] ); n1 -= 128; n1 * (int)(bMeter / 100.0); n2 * (int)(bMeter / 100.0); n1 += 128; n2 += 128; // 加工済みデータを保存 lpData2[ i + 0 ] = n1; lpData2[ i + 1 ] = n2; } よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • php504
  • ベストアンサー率42% (926/2160)
回答No.2

2つずつまわさなくても単純なループでいいと思います for( int i = 0; i < nSize; i++ ) { char n1 = (char)( lpData1[ i ] ); n1 -= 128; n1 = n1 * (bMeter / 100.0); /* 計算結果はちゃんと代入しましょう */ n1 += 128; lpData2[ i ] = n1; } 16ビットのほうもshortにキャストしてやればもっとシンプルになりますよ for( int i = 0; i < nSize/2; i++ ) { short n1 = *((short*)lpData1 + i); n1 = n1 * (bMeter / 100.0); *((short*)lpData2 + i) = n1; }

DEADSPACE566
質問者

お礼

 回答ありがとうございます。 上記の通りにやったら上手くいきました。 キャストを上手くやったらフェード可能になりました。 ありがとうございます。

その他の回答 (1)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

n1 * (int)(bMeter / 100.0); n2 * (int)(bMeter / 100.0); のあたり, 何をしたいの?

DEADSPACE566
質問者

お礼

>この処理をやっても音量がちっとも変わらないんです。 >値が0になれば無音だと思っていたんですが .値が0になると無音ではないようです。 無音は128でした。

DEADSPACE566
質問者

補足

n1 * (int)(bMeter / 100) or n2* (int)(bMeter / 100)は 100分割にして音量を下げています。 (int)は間違いでした。 すいません。 (int) → (char)です。 この処理をやっても音量がちっとも変わらないんです。 値が0になれば無音だと思っていたんですが

関連するQ&A

  • Windowsファイルのサイズの問題

    ネットでWindowsのファイルのサイズを計算するサンプルをみています。 ひとつのサンプルをみても、わからないですので、知っている方に質問したいです。 サンプルは WFDはWIN32_FIND_DATA構造体の変数で、 DWORD dwHigh = WFD.nFileSizeHigh; DWORD dwLow = WFD.nFileSizeLow; __int64 nSize; int nLen; char szTemp[MAX_PATH]; char* p; int nCnt; nSize = dwHigh; nSize = (nSize << 32) + 1023; nSize += dwLow; nSize = (nSize >> 10); //KB単位にする いくつの問題があります。 ●ファイルのサイズは、どうしてこんなに計算するの?  どう計算するの? ●(nSize << 32) とnSize >> 10 はなにをやっているの? よろしくお願いします。

  • 1bppファイルを8bpp(raw)に変換する。

    環境 Windows7 VS2008 SP1 1bppの画像を8bppに変換しようとしているのですが うまくいきません。自分ではこれで 合っていると思うのですが・・・ 何かアドバイスお願いしますm(__)m int Main1bppTo8bpp(WCHAR *filename,int width,int height) { //width,heightは8bppになったときの幅,高さを指定する。 FILE *fpt; _wfopen_s(&fpt,filename,L"rb"); if(fpt==0x00) { MessageBox(NULL,L"1bppTo8bpp Error",L"1bppTo8bpp Error",MB_OK); return -1; } else { unsigned char *layer,*Output; layer=(unsigned char*)calloc(((width/8)+1)*height*sizeof(unsigned char),sizeof(unsigned char)); Output=(unsigned char*)malloc(width*height); //読み込み fread(&layer[0],sizeof(unsigned char),((width/8)+1)*height,fpt); FILE *fpt_output; _wfopen_s(&fpt_output,L"1bppTo8bpp.raw",L"wb"); int i,j,flag=0x00; for(i=0;i<((width/8)+1)*height;i+=((width/8)+1)) { for(j=0;j<((width/8)+1);j++) { //8bit目 if((layer[i+j]&BIT8)==BIT8) { Output[i+j+flag]=0x00; } else { Output[i+j+flag]=0xff; } //7bit目 if((layer[i+j]&BIT7)==BIT7) { Output[i+j+flag+1]=0x00; } else { Output[i+j+flag+1]=0xff; } //6bit目 if((layer[i+j]&BIT6)==BIT6) { Output[i+j+flag+2]=0x00; } else { Output[i+j+flag+2]=0xff; } //5bit目 if((layer[i+j]&BIT5)==BIT5) { Output[i+j+flag+3]=0x00; } else { Output[i+j+flag+3]=0xff; } //4bit目 if((layer[i+j]&BIT4)==BIT4) { Output[i+j+flag+4]=0x00; } else { Output[i+j+flag+4]=0xff; } //3bit目 if((layer[i+j]&BIT3)==BIT3) { Output[i+j+flag+5]=0x00; } else { Output[i+j+flag+5]=0xff; } //2bit目 if((layer[i+j]&BIT2)==BIT2) { Output[i+j+flag+6]=0x00; } else { Output[i+j+flag+6]=0xff; } //1bit目 if((layer[i+j]&BIT1)==BIT1) { Output[i+j+flag+7]=0x00; } else { Output[i+j+flag+7]=0xff; } flag=flag+8; } flag=0x00; } //最終的な「fwrite」はここでする。 fwrite(&Output[0],sizeof(unsigned char),width*height,fpt_output); free(layer); free(Output); fclose(fpt); fclose(fpt_output); } return 0;

  • 2バイトの文字データの送信

    今2バイト分のデータを送信しようと思っているのですが、なかなかうまくいきません。どうしたらいいのでしょうか? (出きればソースを載せていただきたいです。) お願いします。 sample(一部) //送信 SOCKET sTest; char data[2] = 2; for(i=0;i<10;i++){ send(sTest,data,sizeof(data),0); } //受信 #define SIZE 256 SOCKET sTest; int hrecv; char data[SIZE]; while(1){ recv(sTest,data,SIZE,0); if(hrecv == 0){ colsesocket(sTest); break; } }

  • bmpファイルの画像データ表示

    C言語で24bit Windowsbitmapの画像データ部を読み込んで10進数でダンプするプログラムを書きましたが000…と表示されます. バイナリファイルの扱いは初めてなので勘違いを多々しているとおもいます.ご指導,ご指摘宜しくお願いします. =======ソース=========================== #include<stdio.h> #include<stdlib.h> int main(int argc,char *argv[]){ FILE *fp; char buff[40]; char buffData[2560]; size_t size = 1; size_t n = 40; int biSize; int biBitCount; int biCompression; int biWidth; int biHeight; int bfSize; int bfOffBits; int lineByte; int i; int position; int line; if( argc != 2){ printf("Run this way !! %s [bit map image] \n",argv[0]); return 0; } fp = fopen(argv[1],"rb"); if(fp == NULL){ printf("%s No such file or directory !!\n",argv[1]); return 0; } /********************************* * check header infomation * *********************************/ // check input file type fread(buff,size,n,fp); if('B' != buff[0] || 'M' != buff[1]){ printf("## Warning ## %s is not bit map file !!\n",argv[1]); return 0; } // check bitmap type biSize = *(int*)(buff + 14); if( biSize != 40){ printf("%s isn`t Windows bitmap !!\n",argv[1]); return 0; } // check the size(bit) of 1 pixel biBitCount = *(int*)(buff + 28); if(biBitCount != 24){ printf("%s isn't 24bit Windows bitmap !!\n",argv[1]); return 0; } // check the type of compression biCompression = *(int*)(buff + 30); if(biCompression != 0){ printf("%s is compressed Windows bitmap !!",argv[1]); return 0; } // check the width of image (pixel) biWidth = *(int*)(buff + 18); //printf("Width : %d\n",biWidth); // check the height of image (pixel) biHeight = *(int*)(buff + 22); //printf("Height : %d\n",biHeight); // check the file size bfSize = *(int*)(buff + 2); // check the offset to image data bfOffBits = *(int*)(buff + 10); /************************************ * reading image data * ************************************/ // the size of one line lineByte = (biWidth * biBitCount) / 8; printf("LineByte = %d\n",lineByte); for(i=0;i < biHeight ;i++){ position = bfOffBits + lineByte * (biHeight - (i + 1)); fseek(fp,position,SEEK_SET); fread(buffData,line,1,fp); printf("%d\n",*(int*)buffData); } fclose(fp); return 0; } ========================================

  • 構造体のキャスト

    はじめまして。 C言語初心者です。今回の質問は構造体のメンバを他の構造体に格納するときにおきる不可解な現象です。 具体的には、 typedef struct gmsg{ int a; int b; int Dt[4]; }GMSG 上記のDt[4]を以下の構造体に代入していきます。 typedef struct msg{ char a; char b; char c; char d; int e; short f; char g; char h; char i; char j; char k; char l; char m; char n; short o; }MSG この際に以下のような処理を行っています。 この際GMSGを(ポインタ)pt_msgdt,(ポインタ)MSGをpt_SubDtとし、 pt_SubDt->a = (char)(pt_msgdt->Dt[0] ) & 0xFF; pt_SubDt->b = (char)(pt_msgdt->Dt[0] >>8) & 0xFF; pt_SubDt->c = (char)(pt_msgdt->Dt[0] >> 16 ) & 0xff; pt_SubDt->d = (char)(pt_msgdt->Dt[0] >> 24)& 0xff; pt_SubDt->e = (pt_msgdt->Dt[1]) & 0xFFFFFFFF; pt_SubDt->f = (short)(pt_msgdt->Dt[2] & 0xFFFF); pt_SubDt->g = (char)((pt_msgdt->Dt[2] >> 16) & 0xFF); pt_SubDt->h = (char)((pt_msgdt->Dt[2] >> 24 ) & 0xFF); pt_SubDt->i = (char)(pt_msgdt->Dt[3]) & 0xFF; pt_SubDt->j = (char)(pt_msgdt->Dt[3] >> 8) & 0xFF; pt_SubDt->k = (char)(pt_msgdt->Dt[3] >> 16) & 0xFF; pt_SubDt->l = (char)(pt_msgdt->Dt[3] >> 24) & 0xFF; pt_SubDt->m = (char)(pt_msgdt->Dt[4]) & 0xFF; pt_SubDt->n = (char)(pt_msgdt->Dt[4] >> 8) & 0xFF; pt_SubDt->o = (short)(pt_msgdt->Dt[4] >> 16) & 0xFFFF; } しかし処理結果をデバック中にDt[0],Dt[3],Dt[4]の0x79以下のデータはキャストが行いますが,0x80~0xffのデータに関しては4byteになり 0xffffff**といったキャスト結果になってしまいます。 例えると Dt[3]=0x000000f120; 処理結果 h = 0x00 g = 0x00 f = 0xFFFFF120 といった結果になってしまいます。 この結果を0x80以上でもint->char,int->shortのようにキャストく色々な方法を試しましたが、わかりません。 よろしくお願いします。 ちなみにOSはLinux,コンパイラーはC言語で扱っているデータはリトルエンディアンのバイナリデータです。

  • ファイル操作について。

     ファイルのテキストの中の文字列はどのような型で宣言されているか、 わかる人がいたら教えてください。  例えば、fopenでFILE宣言しているstreamにおとして、streamの中から1文字を とる時にfgetcでintのiに入れますよね。この文字をprintするときに%cとやったら ここで、型がint→charに変わってちゃんと表示されるのはわかるのですけれど、SJISの日本語2バイトからなっている物ではそれぞれの情報をi[0],i[1]に格納してそれぞれをchar型に変換して連続して表示しなければならない。そうすると、intが16ビットだとすると(32ビットの時もあるらしいので)、テキストファイルでは1文字が16ビット連続で表されているはずなのに、streamから16bitずつひっぱて8bitに直してから、また、連続して表示しなければ、出力ができないんですよ。  これはテキストファイルからstramのときに1文字の1byteにまた1byteが自動的に てういているように感じるのですけれど、もし、わかる人がいたら教えてください。説明がわかりずらいですけれど。。。。

  • ダブルポインタ?

    下記のような関数が存在し、 最終的には mainで宣言した変数 "a" にDataGetでコピーしたデータを mainで再び使用したいのですが、 下記の方法だとmainに何も帰ってきません。 (NULLのまま・・・) 下記の関数を使用しmainに上手くデータを 引き継ぐためにはどうすれば良いのでしょうか? void Mem(int nSize,void **ptr){ char *tmp; tmp = malloc(nSize); *ptr = tmp; } void DataGet(char *aa,char *a){ int nSize = 5; (void)Mem(nSize,(void **)&a); memcpy(a,aa,nSize); return; } void main(){ char aa[20]; char *a = 0x00; memset(aa,0x00,20); memcpy(aa,"test",4); (void)DataGet(aa,a); /* aデータをここから再び使いたい */ }

  • int型(2バイト)データの分割

    int型(2バイト)データの分割 マイコンのフラッシュ領域にint型のデータ(2バイト)を 1バイトづつ書き込むのに以下のコードを考えています。 unsigned int data; unsigned char dat1,dat2; data = 555; dat1 = 0; dat2 = 0; dat1 = (char)data; dat2 = (char)data >> 8; 以下、dat1とdat2をフラッシュに書き込む。 未熟者でプログラムとして合っているのか解りません。 やり方として問題ないでしょうか? またもっと良い方法があればご教授願います。

  • C言語でファイル読み書きを早くしたい。

    いつも利用させてもらって助かっています。 あるプログラムを作成しているのですが、ファイル入力の部分がネックとなってしまって、全体が使いものにならない状況に陥っています。 たくさんのデータをfread1回で読み込むことにより、読み込み速度はずいぶんと改善されましたが、まだ圧倒的に遅い状況です。システムコールを使いましたが、ほとんど改善されませんでした。 読み込み/書き込みの速度を改善する方法として,SSDメモリを使ったりする方法があると思いますが,プログラムの観点から改善できるところはないでしょうか? 下に、ファイル読み込みの部分だけ記述したコードを添付させて頂いたので、改善できる点があれば、御指摘頂けると助かります。 なお、前提として, (1)データはスタック領域だと不足するので、ヒープ領域に確保 (2)データファイルは改行無しの一連のデータ とします。 ちなみに、環境は OS   : CentOS5.3 memory   : 6GB コンパイラ : gcc です。 よろしくお願いします。 //----------------------------------------------------- //通常バージョン #include <stdio.h> #include <stdlib.h> #define SIZE (512*1024*1024) //500MB int main(void) { unsigned long int i; unsigned char *data; FILE *fp; data = (unsigned char *)malloc(SIZE); if(data == NULL) { printf("メモリが確保できません\n"); exit(EXIT_FAILURE); } fp = fopen("filein.dat", "rb"); fread( data, sizeof( unsigned char), (int)SIZE, fp ); fclose(fp); /* //表示 for( i=0; i<SIZE; i++ ){ printf("%2x", data[i]); } puts(""); */ fp = fopen("fileout.dat", "w"); fwrite( data, sizeof( unsigned char), (int)SIZE, fp); fclose(fp); free(data); return 0; } //----------------------------------------------------- //readシステムコールを使ったバージョン #include <stdio.h> #include <stdlib.h> #define SIZE (512*1024*1024) //500MB int main(void) { unsigned long int i; unsigned char *data; data = (unsigned char *)malloc(SIZE); if(data == NULL) { printf("メモリが確保できません\n"); exit(EXIT_FAILURE); } int fd; fd = open( "filein.dat" ); read( fd, data, sizeof(unsigned char)*SIZE); close(fd); /* //表示 for( i=0; i<SIZE; i++ ){ printf("%2x", data[i]); } puts(""); */ FILE *fp; fp = fopen("fileout.dat", "w"); fwrite( data, sizeof( unsigned char), (int)SIZE, fp); fclose(fp); free(data); return 0; }

  • ネットで落ちていた「Excelで作ったデータ(CSVファイル)の読み込

    ネットで落ちていた「Excelで作ったデータ(CSVファイル)の読み込みプログラム」をそのままコンパイルして実行しようと思ったのですが、 sample.c: In function 'main': sample2.c:9: warning: return type of 'main' is not 'int' と、表示されてしまいます。 プログラミング初心者なので、どこが間違っているのかわかりません。 回答またはアドバイスの程、よろしくお願いいたします。 ネットで落ちていたプログラムを以下に記載します。 sample2.c #include <stdio.h> #define MAX_ITEM_SIZE 100 #define MAX_LINE_SIZE 1024 char *GetCSVItem(char *wp, char *buff, int size); void main(int argc, char *argv[]) { FILE *fp; char buff[MAX_LINE_SIZE], *wp, item[3][MAX_ITEM_SIZE]; int i1, len; if(argc != 2){ printf("コマンドの入力形式が間違っています.\n"); return; } fp = fopen(argv[1], "r"); if(fp == NULL){ printf("ファイルがオープンできません[%s].\n", argv[1]); return; } for(;;){ if(fgets(buff, MAX_LINE_SIZE, fp) == NULL) break; len = strlen(buff); if(len == 0 || buff[len-1] != '\n'){ if(feof(fp) == 0){ printf("データが不正です[%s].\n", buff); return; } } buff[len-1] = '\0'; wp = buff; if((wp = GetCSVItem(wp, item[0], MAX_ITEM_SIZE)) == NULL){ printf("エラー(1)\n"); break; } if((wp = GetCSVItem(wp, item[1], MAX_ITEM_SIZE)) == NULL){ printf("エラー(2)\n"); break; } if((wp = GetCSVItem(wp, item[2], MAX_ITEM_SIZE)) == NULL){ printf("エラー(3)\n"); break; } if(*wp != '\0'){ printf("エラー(4)\n"); break; } for(i1 = 0; i1 < 3; i1++){ printf("%d:%s\n", i1+1, item[i1]); } } fclose(fp); } char *GetCSVItem(char *wp, char *buff, int size) { int i1; buff[0] = '\0'; while(*wp == ' ' || *wp == '\t') wp++; if(*wp == '\0'){ return(NULL); } for(i1 = 0; i1 < MAX_ITEM_SIZE; i1++, wp++){ if(i1 >= size) return(NULL); buff[i1] = *wp; if(*wp == '\0'){ buff[i1] = '\0'; return(wp); } if(*wp == ','){ wp++; buff[i1] = '\0'; break; } } return(wp); }