WAVEの編集(ノイズの付加)・保存

WAVE音声に雑音を付加し,保存する例題です.雑音はrand()関数により発生しており,大きさは0〜10の値で付加しています.

コンパイル例:
Gami[84]% gcc -o rw_wave rw_wave.cpp -lwinmm

WAVEの編集(ノイズの付加)・保存(rw_wave.cpp)
//-----------------------------------------------------------------
// rw_wave.cpp:
//      WAVE ファイルの読込み/書込み
//-----------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//-----------------------------------------------------------------
// for VC++
//#include <windows.h>
//#include <mmsystem.h>
//#pragma comment(lib,"winmm.lib")
//-----------------------------------------------------------------
#ifndef WIN32
// for wave format
// included from mmsystem.h
typedef unsigned char  BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef struct tWAVEFORMATEX {
    WORD wFormatTag;
    WORD nChannels;
    DWORD nSamplesPerSec;
    DWORD nAvgBytesPerSec;
    WORD nBlockAlign;
    WORD wBitsPerSample;
    WORD cbSize;
} WAVEFORMATEX;
#define MAKEFOURCC(c0,c1,c2,c3) ((DWORD)(BYTE)(c0)       | \
                                 ((DWORD)(BYTE)(c1)<<8)  | \
                                 ((DWORD)(BYTE)(c2)<<16) | \
                                 ((DWORD)(BYTE)(c3)<<24))
#define mmioFOURCC(c0,c1,c2,c3) MAKEFOURCC(c0,c1,c2,c3)
#endif
//-----------------------------------------------------------------
typedef struct {
    DWORD fileID,fileSize;
    DWORD fmtID,fmt_type,fmtSize;
    WAVEFORMATEX wfx;
    DWORD dataID,dataSize;
} WAVE_HEADER;
static char chunk_id[12][5] = { // chunk types
    "data","fact","cue ","plst","list","adtl",
    "labl","note","ltxt","smpl","inst","\0"};
//-----------------------------------------------------------------
void err_exit(char* str);
void read_waveheader(FILE** fp,WAVE_HEADER* whdr);
void rw_wave(FILE** fp,WAVE_HEADER whdr,char* ofile);
void disp_waveheader(char* ifile,WAVE_HEADER whdr);
//-----------------------------------------------------------------
int main(int argc,char* argv[])
{
    FILE* fp;
    char *ifile;
    WAVE_HEADER whdr;
    // ファイル名
    if(argc >= 2) ifile = argv[1];
    else err_exit("Insufficient argument.\n");
    // 読込み開始
    fp = fopen(ifile,"rb");
    if(fp==NULL) err_exit("input file cannot open.\n");
    // ヘッダ情報の読み込み
    read_waveheader(&fp,&whdr);

    disp_waveheader(ifile,whdr);
    
    // 再生開始
    rw_wave(&fp,whdr,"output.wav");
    // 後片付け
    fclose(fp);
    
    return 0;
}

void err_exit(char* str)
{
    fprintf(stderr,str);
    exit(0);
}

void read_waveheader(FILE** fp,WAVE_HEADER* whdr)
{
    int i,find,idck=1;
    DWORD drTmp;
    char tag[4];
    // file head
    fread(&whdr->fileID  ,sizeof(DWORD),1,*fp);
    fread(&whdr->fileSize,sizeof(DWORD),1,*fp);
    // fmt head
    fread(&whdr->fmtID   ,sizeof(DWORD),1,*fp);
    fread(&whdr->fmt_type,sizeof(DWORD),1,*fp);
    fread(&whdr->fmtSize ,sizeof(DWORD),1,*fp);
    fread(&whdr->wfx     ,sizeof(WAVEFORMATEX)-sizeof(WORD),1,*fp);
    // check chunk info.
    whdr->dataID     = 0;
    whdr->dataSize   = 0;
    whdr->wfx.cbSize = 0;
    // check other format
    fseek(*fp,-2,SEEK_CUR);
    while(idck){
        if(ftell(*fp) > whdr->fileSize) break;
        fread(tag,sizeof(char),4,*fp);
        find = 0;
        for(i=0;;i++){
            if(chunk_id[i][0] == '\0') break;
            if(!strncmp(tag,"data",4)){
                whdr->dataID = mmioFOURCC('d','a','t','a');
                fread(&whdr->dataSize,sizeof(DWORD),1,*fp);
                find = 1; idck = 0;
                break;
            } else {
                if(!strncmp(tag,chunk_id[i],4)){
                    find = 0;
                    fread(tag,sizeof(char),4,*fp);
                    drTmp = mmioFOURCC(tag[0],tag[1],tag[2],tag[3]);
                    fseek(*fp,ftell(*fp)+drTmp,SEEK_SET);
                    break;
                }
            }
        }
        if(!find) fseek(*fp,ftell(*fp)-(sizeof(DWORD)-1),SEEK_SET);
    }
}

void rw_wave(FILE** fpIn,WAVE_HEADER whdr,char* ofile)
{
    int i;
    // 入力用
    WAVEFORMATEX* f = &whdr.wfx;
    DWORD rc,fmtLen,i_flame,n_flame;
    DWORD block_size = (f->nChannels*f->nSamplesPerSec*f->wBitsPerSample/8/
                        f->nBlockAlign) * f->nBlockAlign;
    BYTE *wav;
    // 出力用
    FILE *fpOut;
    DWORD wc,cbsize,wave_fsize,dwTmp;
    //--------------------------------------------------
    // 再生用WAVEフォーマットの設定
    //--------------------------------------------------
    fmtLen = sizeof(DWORD)*7+sizeof(WAVEFORMATEX)-sizeof(WORD);
    wav    = (char*)malloc(block_size);
    //--------------------------------------------------
    // 出力用WAVEファイル
    //--------------------------------------------------
    if((fpOut=fopen(ofile,"wb")) == NULL){
        fprintf(stderr,"\ncan not output wave!\n"); return;
    }
    //--------------------------------------------------
    // ヘッダ部の出力
    //--------------------------------------------------
    cbsize = sizeof(WAVEFORMATEX)-sizeof(WORD);
    dwTmp = mmioFOURCC('R','I','F','F');
    fwrite(&dwTmp,1,sizeof(DWORD),fpOut);
    dwTmp = whdr.dataSize + sizeof(char)*12+sizeof(DWORD)*2+cbsize;
    fwrite(&dwTmp,1,sizeof(DWORD),fpOut);
    dwTmp = mmioFOURCC('W','A','V','E');
    fwrite(&dwTmp,1,sizeof(DWORD),fpOut);
    dwTmp = mmioFOURCC('f','m','t',' ');
    fwrite(&dwTmp,1,sizeof(DWORD),fpOut);
    fwrite(&cbsize,1,sizeof(DWORD),fpOut);
    fwrite((void*)f,1,cbsize,fpOut);
    dwTmp = mmioFOURCC('d','a','t','a');
    fwrite(&dwTmp,1,sizeof(DWORD),fpOut);
    dwTmp = whdr.dataSize;
    fwrite(&dwTmp,1,sizeof(DWORD),fpOut);
    //--------------------------------------------------
    // 読込み
    //--------------------------------------------------
    i_flame = 0;
    n_flame = whdr.dataSize/block_size;
    printf("\n**data sec = %ld [sec]\n",n_flame);
    fprintf(stdout,"Frame: %4d/%4d",i_flame,n_flame);
    fflush(stdout);
    srand(time(NULL));
    while(1){
        // WAVE音声の読込み
        rc = fread(wav,1,block_size,*fpIn);
        
        // 雑音の付加
        for(i=0;i<rc;i++){
            wav[i] += rand()%10;
        }
        
        // 出力
        wc = fwrite(wav,1,rc,fpOut);
        fprintf(stdout,"\rFrame: %4d/%4d",++i_flame,n_flame);
        fflush(stdout);
        if(rc != block_size) break;
    }
    fputs("\n",stdout); fflush(stdout);
    // 後片付け
    free(wav);
    fclose(fpOut);
}

//-----------------------------------------------------------------
// WAVE format の表示
//-----------------------------------------------------------------
void disp_waveheader(char* ifile,WAVE_HEADER whdr)
{
    char tag[5]; tag[4] = 0;
    printf("FILE: %s\n",ifile);
    printf("**FILE HEAD\n");
    memcpy(tag,&whdr.fileID,sizeof(DWORD));
    printf("    FILE ID: %s\n",tag);
    printf("  FILE SIZE: %ld[Byte]\n",whdr.fileSize);
    printf("**WAVE FORMAT\n");
    memcpy(tag,&whdr.fmtID,sizeof(DWORD));
    printf("  FORMAT ID: %s\n",tag);
    memcpy(tag,&whdr.fmt_type,sizeof(DWORD));
    printf("FORMAT TYPE: %s\n",tag);
    printf("FORMAT SIZE: %ld\n",whdr.fmtSize);
    printf("**WAVE INFO.\n");
    printf("   WAVE TAG: %d\n",whdr.wfx.wFormatTag);
    printf("    CHANNEL: %d\n",whdr.wfx.nChannels);
    printf(" SAMPLE/SEC: %ld\n",whdr.wfx.nSamplesPerSec);
    printf("BYTE/SAMPLE*CHANNEL: %d\n",whdr.wfx.nBlockAlign);
    printf(" BIT/SAMPLE: %d\n",whdr.wfx.wBitsPerSample);
    if(whdr.wfx.cbSize){
        printf("EXTRA FORMAT SIZE: %d\n",whdr.wfx.cbSize);
    }
    printf("**WAVE DATA INFO.\n");
    if(whdr.dataID){
        memcpy(tag,&whdr.dataID,sizeof(DWORD));
        printf("    DATA ID: %s\n",tag);
    } else {
        printf("    DATA ID: null\n");
    }
    printf("  DATA SIZE: %ld[Byte]\n",whdr.dataSize);
}
inserted by FC2 system