モノラル化

ステレオWAVファイルからモノラルのWAVファイルにします。
左チャンネルのみと右チャンネルのみ、左右のチャンネルを
mixしたものを一度に作成します。
#include <stdio.h>
#include <string.h>
 
#define FileName "Warp1_ste.wav" //適当な曲を探して下さい。
 
// defines
#define STR_RIFF    "RIFF"
#define STR_WAVE    "WAVE"
#define STR_fmt     "fmt "
#define STR_data    "data"
 
#define WAV_MONAURAL    1
#define WAV_STEREO      2
 
#pragma pack(push,1)
struct WaveFileHeader{
    char            Riff[4];         // RIFFヘッダ
    unsigned int    FileSize;         // ファイルサイズ - 8
    char            Wave[4];         // WAVEヘッダ
};
 
struct TagChank{
    unsigned char   Fmt[4]; // fmt チャンク
    unsigned int    FmtSize;      // fmt チャンクのバイト数
};
 
struct WaveFormat{
    unsigned short  FormatTag;          // フォーマットID
    unsigned short  Channels;           // チャンネル数
    unsigned int    SamplingRate;      // サンプリングレート
    unsigned int    BytesPerSec;        // データ速度 (Byte/sec)
    unsigned short  BlockAlign;         // ブロックサイズ
    unsigned short  BitsPerSample;      // サンプルあたりのビット数
};
 
struct tagWrSWaveFileHeader
{
    unsigned char   hdrRiff[4];         // 'RIFF'
    unsigned int    sizeOfFile;         // ファイルサイズ - 8
    unsigned char   hdrWave[4];         // 'WAVE'
    unsigned char   hdrFmt[4];          // 'fmt '
    unsigned int    sizeOfFmt;          // sizeof( PCMWAVEFORMAT )
    struct {
        unsigned short  formatTag;      // WAVE_FORMAT_PCM
        unsigned short  channels;       // number of channels
        unsigned int    samplesPerSec;  // sampling rate
        unsigned int    bytesPerSec;    // samplesPerSec * channels * (bitsPerSample/8)
        unsigned short  blockAlign;     // block align
        unsigned short  bitsPerSample;  // bits per sampling
    } stWaveFormat;                     // PCMWAVEFORMAT
    unsigned char   hdrData[4];         // 'data'
    unsigned int    sizeOfData;         // Waveデーターサイズ
};
#pragma pack(pop)
 
WaveFileHeader waveFileHeader;
WaveFormat  waveFmtPcm;
TagChank          chank;
 
//8 bits/sampling
 
int efffect8BitWav(FILE *fpIn, FILE *fpOut, long sizeOfData, int LR)
{
    unsigned int  i;
    unsigned short mix;
    unsigned char  In[2];
    unsigned char  Out;
 
    for (i = 0; i < sizeOfData / sizeof In; i++)
    {
        if(fread( In, sizeof In, 1, fpIn) != 1)
            return -1;
 
if(LR==2){
mix = ((unsigned short)In[0] +(unsigned short)In[1]) / (unsigned short)2;
        Out=(unsigned char)mix;
 
        if(fwrite(&Out, sizeof Out, 1, fpOut) != 1)
            return -1;
}else{
        if (fwrite(In, sizeof In[LR], 1, fpOut) != 1)
            return -1;
}
    }
    return 0;
}
 
 
// 16 bits/sampling
int efffect16BitWav(FILE *fpIn, FILE *fpOut, long sizeOfData, int LR)
{
    unsigned int  i;
    int   mix;
    short In[2];
    short Out;
 
    for (i = 0; i < sizeOfData / sizeof In; i++)
    {
        if(fread( In, sizeof In, 1, fpIn) != 1)
            return -1;
 
if(LR==2){
       mix = ((int)In[0] +(int)In[1]) / (int)2;
        Out=(short)mix;
 
        if(fwrite(&Out, sizeof Out, 1, fpOut) != 1)
            return -1;
}else{
 
        if (fwrite(In, sizeof In[LR], 1, fpOut) != 1)
            return -1;
}
    }
    return 0;
}
 
 
 
// wav ヘッダ 書き込み
long wavHeaderWrite(FILE *fp, long sizeOfData, unsigned short ch, unsigned long sampRate, unsigned short sampBits)
{
    unsigned short bytes;
    tagWrSWaveFileHeader wrWavHdr;
 
    strncpy((char *)wrWavHdr.hdrRiff,STR_RIFF,sizeof wrWavHdr.hdrRiff); // RIFF ヘッダ
 
    wrWavHdr.sizeOfFile=sizeOfData + sizeof(wrWavHdr) - 8;      // ファイルサイズ
 
    strncpy((char *)wrWavHdr.hdrWave,STR_WAVE,sizeof wrWavHdr.hdrWave); // WAVE ヘッダ
 
    strncpy((char *)wrWavHdr.hdrFmt,STR_fmt,sizeof wrWavHdr.hdrFmt);    // fmt チャンク
 
    wrWavHdr.sizeOfFmt= sizeof wrWavHdr.stWaveFormat;           // fmt チャンク,無圧縮wav は 16
 
    wrWavHdr.stWaveFormat.formatTag=1;                          // 無圧縮PCM = 1
 
    wrWavHdr.stWaveFormat.channels=ch;                          // ch (mono=1, stereo=2)
 
    wrWavHdr.stWaveFormat.samplesPerSec=sampRate;               // sampleng rate(Hz)
 
    bytes = sampBits / 8;                                       // bytes/sec
    wrWavHdr.stWaveFormat.bytesPerSec = bytes * ch * sampRate;
 
    wrWavHdr.stWaveFormat.blockAlign=bytes * ch;                // byte/サンプル*チャンネル
 
    wrWavHdr.stWaveFormat.bitsPerSample=sampBits;               // bit/サンプル
 
    strncpy((char *)wrWavHdr.hdrData,STR_data,sizeof wrWavHdr.hdrData); // dataチャンク
 
    wrWavHdr.sizeOfData=sizeOfData;                             // データ長 (byte)
 
    fwrite(&wrWavHdr, sizeof wrWavHdr, 1, fp);                  // write header
 
    return ftell(fp);
}
 
 
// wav データ書き込み
int wavDataWrite(FILE *fpIn, FILE *fpOut, long posOfData,long sizeOfData, short bytesPerSingleCh, int LR)
{
    fseek(fpIn, posOfData, SEEK_SET);    //元ファイルのデータ開始部分へ
 
if( bytesPerSingleCh==1){
        return efffect8BitWav(fpIn, fpOut, sizeOfData, LR);
}else{
        return efffect16BitWav(fpIn, fpOut, sizeOfData, LR);
}
}
 
// ファイル内容書き出し
int wavWrite(char *inFile, char *outFile, unsigned long sampRate, unsigned short sampBits, long posOfData, long sizeOfData, int LR)
{
    unsigned short bytesPerSingleCh;
    FILE *fpIn, *fpOut;
 
    if((fpOut = fopen(outFile, "wb")) == NULL)
    {
        fprintf(stderr, "%s をオープンできません.\n", outFile);
        return -1;
    }
 
    bytesPerSingleCh = sampBits / 8;
 
    // wav ヘッダ書き込み
    if(wavHeaderWrite(fpOut, sizeOfData/2, WAV_MONAURAL, sampRate, sampBits) != 44)
    {
        fprintf(stderr, "ヘッダを書き込めません: %s\n", outFile);
        fclose(fpOut);
        return -1;
    }
 
    if((fpIn = fopen(inFile, "rb")) == NULL)
    {
        fprintf(stderr, "%s をオープンできません.\n", inFile);
        fclose(fpOut);
        return -1;
    }
 
    // wav データ書き込み
    if(wavDataWrite(fpIn, fpOut, posOfData, sizeOfData, bytesPerSingleCh, LR)!=0)
    {
        fprintf(stderr, "wavDataWriteでエラー発生.\n");
        fclose(fpIn);
        fclose(fpOut);
        return -1;
    }
 
    fclose(fpIn);
    fclose(fpOut);
 
    return 0;
}
 
 
bool readfmtChunk(FILE *fp, WaveFormat* waveFmtPcm){
    if(fread(waveFmtPcm, sizeof(WaveFormat), 1, fp) != 1)return false;
 
    printf( "データ形式: %u (1 = PCM)\n", waveFmtPcm->FormatTag);
    printf( "チャンネル数: %u\n", waveFmtPcm->Channels);
    printf( "サンプリング周波数: %lu [Hz]\n", waveFmtPcm->SamplingRate);
    printf( "バイト数 / 秒: %lu [bytes/sec]\n", waveFmtPcm->BytesPerSec);
    printf( "バイト数×チャンネル数: %u [bytes]\n", waveFmtPcm->BlockAlign);
    printf( "ビット数 / サンプル: %u [bits/sample]\n", waveFmtPcm->BitsPerSample);
 
if(waveFmtPcm->Channels != 2)
    {
        printf( "\nこのプログラムはステレオのファイルを対象とします.\n");
        printf( "このwavファイルのチャンネル数は %d です.\n", waveFmtPcm->Channels);
        return false;
    }
    if(waveFmtPcm->FormatTag != 1)
    {
        printf( "\nこのプログラムは無圧縮PCMのみを対象とします.\n");
        printf( "このwavファイルの形式は %04X です.\n", waveFmtPcm->FormatTag);
        return false;
    }
    if(waveFmtPcm->BitsPerSample != 8 && waveFmtPcm->BitsPerSample != 16)
    {
        printf( "\nこのプログラムは8/16ビットサンプリングされたものを対象とします\n");
        printf( "このwavファイルの bits/secは %d です.\n", waveFmtPcm->BitsPerSample);
        return false;
    }
    return true;
}
 
 
 
bool WaveHeaderRead(char *wavefile){
    long fPos, len;
    FILE *fp;
errno_t err;
 
    if (err=fopen_s(&fp,wavefile, "rb") !=0){
        printf(" %sをオープンできません\n", wavefile);
        return false;
    }
    printf( "\n%s :\n", wavefile);
 
    // ヘッダ情報
    if (fread(&waveFileHeader, sizeof waveFileHeader, 1, fp) != 1){
        printf(" %ld で読み込み失敗\n", ftell(fp));
        fclose(fp);
        return false;
    }
 
if(strncmp( waveFileHeader.Riff, "RIFF", 4) != 0){
        printf("'RIFF' フォーマットでない\n");
        fclose(fp);
        return false;
    }
 
    // WAVE ヘッダ情報
if (memcmp(waveFileHeader.Wave, "WAVE", 4) != 0){
        printf("'WAVE' が無い\n");
        fclose(fp);
        return false;
    }
 
    // 4Byte これ以降のバイト数 = (ファイルサイズ - 8)(Byte)
len = waveFileHeader.FileSize;
 
    // チャンク情報
    while (fread(&chank, sizeof chank, 1, fp) == 1){
if(memcmp( chank.Fmt, "fmt ", sizeof chank.Fmt) == 0){
            len=chank.FmtSize;
            printf("\"fmt \"の長さ: %ld [bytes]\n\n", len);
            fPos = ftell(fp);
            if(! readfmtChunk( fp, &waveFmtPcm))return false;
            fseek(fp, fPos + len, SEEK_SET);
        }else if(memcmp(chank.Fmt, "data", 4) == 0){
            len = chank.FmtSize;
            printf("\n\"data\" の長さ: %ld [bytes]\n", len);
            fPos = ftell(fp);
            fseek(fp, len + fPos - 4, SEEK_SET);
            break;
        }else{
            len=chank.FmtSize;
            printf( "\"%c%c%c%c\"の長さ: %ld [bytes]\n\n",
chank.Fmt[0],chank.Fmt[1],
chank.Fmt[2],chank.Fmt[3], len);
            fPos = ftell(fp);
            fseek(fp, fPos + len, SEEK_SET);
        }
    }
    fclose(fp);
 
    return true;
}
 
 
void main(int argc, char *argv[]){
    WaveHeaderRead(FileName);
 
//0=L 1=R 2=mix
if( wavWrite(FileName, "monoL.wav", waveFmtPcm.SamplingRate, waveFmtPcm.BitsPerSample, 0, waveFileHeader.FileSize,0)!=0)
        return;
if( wavWrite(FileName, "monoR.wav", waveFmtPcm.SamplingRate, waveFmtPcm.BitsPerSample, 0, waveFileHeader.FileSize,1)!=0)
        return;
if( wavWrite(FileName, "monoM.wav", waveFmtPcm.SamplingRate, waveFmtPcm.BitsPerSample, 0, waveFileHeader.FileSize,2)!=0)
        return;
getchar();
}
 

 

 

 

最終更新:2013年03月03日 15:02