カラオケ化

 完全ではありませんが .wav ファイルからボーカルを除去します。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
 
using namespace std;
 
#define INFileName "sound.wav"
#define OUTFileName "karaoke.wav"
#define PAI   3.141592653589793
#define Length 3.00
 
 
// 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 WrSWaveFileHeader
{
    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データーサイズ
};
 
//関数間の引数
struct TagParam
{
    unsigned int    sizeOfData;         // Waveデーターサイズ
    unsigned short  channels;           // チャンネル数
    unsigned int    samplesPerSec;      // Hz
    unsigned int    bytesPerSec;        // バイト数/sec
    unsigned short  bitsPerSample;      // 8 bits or 16 bits
    long            posOfData;          // position of begnning of WAV datas
float           secPerCycle;        // 間隔:秒
    long            cycleuSec;          // 間隔:μ秒
float           fAmp;               // ボリューム倍率
};
#pragma pack(pop)
 
WaveFileHeader waveFileHeader;
WaveFormat  waveFmtPcm;
TagChank chank;
TagParam sp;
 
// wav ヘッダ作成
long wavHeaderWrite(FILE *fp, TagParam* sp)
{
    unsigned short bytes;
WrSWaveFileHeader wHdr;
 
    strncpy((char *)wHdr.hdrRiff,STR_RIFF,sizeof wHdr.hdrRiff);   // RIFF ヘッダ
 
    wHdr.sizeOfFile=sp->sizeOfData+sizeof(WrSWaveFileHeader)-8;// ファイルサイズ
 
    strncpy((char *)wHdr.hdrWave,STR_WAVE,sizeof wHdr.hdrWave);   // WAVE ヘッダ
 
    strncpy((char *)wHdr.hdrFmt,STR_fmt,sizeof wHdr.hdrFmt);      // fmt チャンク
 
    wHdr.sizeOfFmt=sizeof wHdr.stWaveFormat;              // fmt チャンク,無圧縮wav は 16
 
    wHdr.stWaveFormat.formatTag=1;                         // 無圧縮PCM = 1
 
    wHdr.stWaveFormat.channels=sp->channels;               // ch (mono=1, stereo=2)
 
    wHdr.stWaveFormat.samplesPerSec=sp->samplesPerSec;     // sampleng rate(Hz)
 
    bytes = sp->bitsPerSample / 8;                          // bytes/sec
    wHdr.stWaveFormat.bytesPerSec=
                bytes * sp->channels * sp->samplesPerSec;   // bytes / sec
 
    wHdr.stWaveFormat.blockAlign=bytes * sp->channels;     // byte/サンプル*チャンネル
 
    wHdr.stWaveFormat.bitsPerSample=sp->bitsPerSample;     // 16 bit / sample
 
    strncpy((char *)wHdr.hdrData,STR_data,sizeof wHdr.hdrData);   // dataチャンク
 
    wHdr.sizeOfData=sp->sizeOfData;                        // データ長 (byte)
 
fwrite(&wHdr, sizeof wHdr, 1, fp);                  // write header
 
return ftell(fp);
}
 
 
// 8 bits/sampling
 
int efffect8BitWav(FILE *fpIn, FILE *fpOut, TagParam* sp)
{
    unsigned int  i;
    unsigned char In[2];
    int tmpL,tmpR,L,R;
 
    long oneSampleData=(sp->bitsPerSample/8)*sp->channels;
 
    for (i = 0; i < sp->sizeOfData / oneSampleData ; i++)
    {
        if(fread( In, sizeof In, 1, fpIn) != 1)
            return -1;
 
        tmpL=In[0]-128;
        tmpR=In[1]-128;
        L=tmpL-tmpR;
        R=tmpR-tmpL;
        L=max(-128,min(127,L));
        R=max(-128,min(127,R));
        In[0]=(unsigned char)(L+128);
        In[1]=(unsigned char)(R+128);
 
        if (fwrite(In, sizeof In, 1, fpOut) != 1)
            return -1;
    }
    return 0;
}
 
 
// 16 bits/sampling
int efffect16BitWav(FILE *fpIn, FILE *fpOut, TagParam* sp)
{
unsigned int  i;
    short In[2];
    int   L,R;
 
    long oneSampleData=(sp->bitsPerSample/8)*sp->channels;
 
    for (i = 0; i < sp->sizeOfData / oneSampleData ; i++)
    {
        if(fread( In, sizeof In, 1, fpIn) != 1)
            return -1;
 
        L=(int)In[0]-(int)In[1];
        R=(int)In[1]-(int)In[0];
        L=max(-32768,min(32767,L));
        R=max(-32768,min(32767,R));
        In[0]=(short)L;
        In[1]=(short)R;
 
 
        if (fwrite(In, sizeof In, 1, fpOut) != 1)
            return -1;
    }
    return 0;
}
 
 
//wav データ書き込み
int wavDataWrite(FILE *fpIn, FILE *fpOut, TagParam* sp)
{
    int rVal;
 
    fseek(fpIn, sp->posOfData, SEEK_SET);    //元ファイルのデータ開始部分へ
 
    if(sp->bitsPerSample==8)
        rVal=efffect8BitWav(fpIn, fpOut, sp);
    else
        rVal=efffect16BitWav(fpIn, fpOut, sp);
 
    return rVal;
}
 
 
// ファイル内容書き出し
int wavWrite(char *inFile, char *outFile, TagParam* sp)
{
    FILE *fpIn, *fpOut;
 
    if((fpOut = fopen(outFile, "wb")) == NULL)
    {
        printf("%s をオープンできません.\n", outFile);
        return -1;
    }
 
    if(wavHeaderWrite(fpOut, sp) != 44)         // wav ヘッダ書き込み
    {
        printf("ヘッダを書き込めません: %s\n", outFile);
        fclose(fpOut);
        return -1;
    }
 
    if((fpIn = fopen(inFile, "rb")) == NULL)
    {
        printf("%s をオープンできません.\n", inFile);
        fclose(fpOut);
        return -1;
    }
 
    if(wavDataWrite(fpIn, fpOut, sp )!=0)       // wav データ書き込み
    {
        printf("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, TagParam* sp){
    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;
sp->samplesPerSec=waveFmtPcm.SamplingRate;     // サンプリング周波数(Hz)
sp->bitsPerSample=waveFmtPcm.BitsPerSample;     // サンプリングビット数
sp->channels=waveFmtPcm.Channels;               // チャンネル数
sp->bytesPerSec=waveFmtPcm.BytesPerSec;         // バイト数/sec
            fseek(fp, fPos + len, SEEK_SET);
        }else if(memcmp(chank.Fmt, "data", 4) == 0){
            len = chank.FmtSize;
sp->sizeOfData=chank.FmtSize;
            printf("\n\"data\" の長さ: %ld [bytes]\n", len);
            fPos = ftell(fp);
sp->posOfData=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[]){
 
 
sp.secPerCycle=Length;           
 
    WaveHeaderRead(INFileName,&sp);
 
if(sp.channels==1)
    {
        printf("\n入力ファイルはステレオでなければなりません.\n");
        return;
    }
 
    wavWrite(INFileName , OUTFileName, &sp);
 
    printf("\n%s を %sへ変換しました.\n", INFileName, OUTFileName);
getchar();
        return;
}

 

 

 

 

 

 

最終更新:2013年05月02日 21:58