完全ではありませんが .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;
}
|