// .cpp - чтение из файла, внесение эхо, добавление шума, запись в новый файл
#include "record.h"
#define N2 22050
using namespace std;
::IDirectSound8 *pDirectSound; //Глобально определим интерфес
bool flag_record=0;
DWORD dwDataSize =0;
DWORD fact1=0;
//write
HMMIO hmmioOut = NULL; // handle to open output WAVE file
MMCKINFO ckOutRIFF;
MMCKINFO ckOut;
PCMWAVEFORMAT pcmWaveFormat;
MMIOINFO mmioinfoOut;
long lSamples; // number of samples
//
record::record(QWidget *parent, Qt::WFlags flags)
: QWidget(parent, flags)
{
ui.setupUi(this);
m_hRecord=NULL;
}
record::~record()
{
}
void record::on_pushButton_clicked(bool bn)
{
if(bn==true)
{
func(1, "Sound10.wav");
}
else flag_record=0;
ui.pushButton->setChecked(false);
}
bool record::func(int isk, QString File_name_record)
{
File_Name="out.wav";
QFile outfile(File_Name);
setlocale(LC_ALL,"Russian"); //Локаль
::DirectSoundCreate8(0,&pDirectSound,NULL); //Использовать будем 8-е иксы
pDirectSound->SetCooperativeLevel(::GetForegroundWindow(),DSSCL_NORMAL); //Закажем уровень доступа как стандартный
ifstream file("D:\\Sounds\\Iskaz0\\Sound6.wav"/*File_name_record*/,ios::beg | ios::in|ios::binary); //Наша wav'ка
if (!file)
QMessageBox::warning(0,"error","error open file");
DWORD dwRIFF = 0; //И так идет формат wav-файла, он относится к RIFF-файлам, поэтому читаем 4 байта структуы
file.read((char*) &dwRIFF,4);
if (dwRIFF != MAKEFOURCC('R','I','F','F')) //Если RIFF не получили, то значит какую то залепу открыли
{
cout<<"Файл не является RIFF - formated"<<endl;
return 0;
}
file.ignore(4); //Пропустим 4 байта там какая то охинея нам совершенно не нужна
DWORD dwWave = 0; //Секция WAVE
DWORD dwFormat = 0; // Секция fmt /формат файла/
long lSizeFmt = 0; //Размер секции fmt
file.read((char*)&dwWave,4); //Читаем 4 байта, там для Wav-файла должно быть название секции WAVE
if (dwWave != MAKEFOURCC('W','A','V','E')) //Проверим
{
cout<<"Файл не имеет секции WAVE"<<endl;
return 0;
}
file.read((char*)&dwFormat,4); //Если все ОК... То читаем
if (dwFormat != MAKEFOURCC('f','m','t',' ')) //Если секция fmt - не найдена
{
cout<<"Файл не имеет Format(fmt)-Секции "<<endl;
return 0;
}
file.read((char*)&lSizeFmt,4); //Еще читаем 4 байта, там у нас размер секции формат, где идет сам формат + может идти всякая охинея, формат лежит в 16 байтах
WAVEFORMATEX WaveFormat = WAVEFORMATEX(); //Определим структуру винды
file.read((char*)&WaveFormat,16); //Прочитаем ее
file.ignore(lSizeFmt-16); //Пропустим охинею
if (WaveFormat.wFormatTag != 1) //Если таг <>1 то значит есть компрессия файла, ее разбирать мы не будем, работаем не с жатыми данными
{
cout<<"Файл имеет компрессию"<<endl;
return 0;
}
DWORD dwSection = 0; //Следующая секция у нас или fact(Не обязательная) или data(это как раз наш звук)
file.read((char*)&dwSection,4); //Читаем заголовок
if (dwSection == MAKEFOURCC('f','a','c','t')) //Если все же fact - то пропускаем ее
{
cout<<"Файл имеет секцию fact"<<endl;
DWORD dwSizeFact = 0;
file.read((char*)&dwSizeFact,4);
file.ignore(dwSizeFact);
file.read((char*)&dwSection,4);
fact1=dwSection;
}
if (dwSection != MAKEFOURCC('d','a','t','a')) //Ну а теперь сама data - это то, над чем мы будем работать
{
cout<<"Не найдена секция data"<<endl;
return 0;
}
file.read((char*)&dwDataSize,4); //Прочитаем ее размер
char *pData = new char[dwDataSize]; //Динамически выделим переменную типа char[размер звуковых данных]
file.read(pData,dwDataSize); //Прочитаем в нее все звуковые данные
file.close(); //Закроем файл, он нам уже не нужен, у нас есть pData
//И так реализация эха
char *pDataEcho = new char[dwDataSize+int(1.5*WaveFormat.nAvgBytesPerSec)]; //Введем новую указатель на данные и увеличим его на 1.5(секунды) * Байты в секунду
memset(pDataEcho,0,dwDataSize+1.5*WaveFormat.nAvgBytesPerSec); //обнулим его
for (int i = 0; i<dwDataSize; i++) //Обходим весь массив (исходных данных) которые из файла вытащили
{
//Теперь по принципу сумматора складываем данные
pDataEcho[i] += pData[i]; //Текущий байт (исходны) данных
if(isk==0)
{
pDataEcho[i]=pData[i];
}
if(isk==1)
{
pDataEcho[i+int(0.5*WaveFormat.nAvgBytesPerSec)]+= 0.6 * pData[i]; //Сдвигаем на 0.5 секунд и слогаем текущий(исходный) байт * на коэффициент первого затухания
}
if(isk==2)
{
pDataEcho[i+int(0.5*WaveFormat.nAvgBytesPerSec)]+= 0.6 * pData[i]; //Сдвигаем на 0.5 секунд и слогаем текущий(исходный) байт * на коэффициент первого затухания
pDataEcho[i+int(1*WaveFormat.nAvgBytesPerSec)]+= 0.3 * pData[i]; //Сдвигаем на 1 секунду и так же (только коэффициент 0.3)
}
if(isk==3)
{
pDataEcho[i+int(0.5*WaveFormat.nAvgBytesPerSec)]+= 0.6 * pData[i]; //Сдвигаем на 0.5 секунд и слогаем текущий(исходный) байт * на коэффициент первого затухания
pDataEcho[i+int(1*WaveFormat.nAvgBytesPerSec)]+= 0.3 * pData[i]; //Сдвигаем на 1 секунду и так же (только коэффициент 0.3)
pDataEcho[i+int(1.5*WaveFormat.nAvgBytesPerSec)]+= 0.1 * pData[i]; //И последняя волна через 1.5 секунды которая дойдет (коэф. 0.1) -почти не ощутимый
}
}
pData = pDataEcho; //Заменим данные
char *mass;
for (int i = 0; i<dwDataSize; i++) //Обходим весь массив (исходных данных) которые из файла вытащили
{
if(isk==1)
{
pDataEcho[i]=pData[i]+qrand()/1000;
}
if(isk==2)
{
pDataEcho[i]=127-pData[i];
pDataEcho[i]=pData[i]+qrand()/1000;
}
if(isk==3)
{
pDataEcho[i]=127-pData[i];
pDataEcho[i]=pData[i]+qrand()/400;
}
}
pData = pDataEcho; //Заменим данные
dwDataSize+=WaveFormat.nAvgBytesPerSec; //Увеличим размер, что бы DS прочитал добавление 1.5 секунды
//Ну вот и все... Эхо - не реальное, в природе наверное такого добится не возможно, но я же для примера только
// Write the PCMWAVEFORMAT structure
//----------------------------------------------
pcmWaveFormat.wf.wFormatTag=WAVE_FORMAT_PCM;
pcmWaveFormat.wf.nChannels=1;
pcmWaveFormat.wf.nBlockAlign=2;
pcmWaveFormat.wf.nSamplesPerSec=N2;
pcmWaveFormat.wf.nAvgBytesPerSec=N2*2;
pcmWaveFormat.wBitsPerSample=16;
//----------------------------------------------
hmmioOut = mmioOpen(L"out.wav", NULL,
MMIO_ALLOCBUF | MMIO_WRITE | MMIO_CREATE);
if (hmmioOut == NULL)
cout<<"error opening out file "<<endl;
// Write the PCMWAVEFORMAT structure
ckOutRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E');
if (mmioCreateChunk(hmmioOut, &ckOutRIFF, MMIO_CREATERIFF) != 0)
cout<<"error creating out file wave "<<endl;
ckOut.ckid = mmioFOURCC('f', 'm', 't', ' ');
if (mmioCreateChunk(hmmioOut, &ckOut, 0) != 0)
cout<<"error creating out file fmt "<<endl;
if (mmioWrite(hmmioOut, (HPSTR) &pcmWaveFormat, sizeof(pcmWaveFormat))
!= sizeof(pcmWaveFormat))
cout<<"error writing size of fmt "<<endl; // cannot write file, probably
if (mmioAscend(hmmioOut, &ckOut, 0) != 0)
cout<<"error writing size of fmt 2 "<<endl; // cannot write file, probably
ckOut.ckid = mmioFOURCC('d', 'a', 't', 'a');
if (mmioCreateChunk(hmmioOut, &ckOut, 0) != 0)
cout<<"error creating out file data "<<endl;
// Write/read in file of the I/O buffers.
for (int lSamples =2*N2; lSamples > 0; lSamples--)
{
if (mmioinfoOut.pchNext == mmioinfoOut.pchEndWrite)
{
mmioinfoOut.dwFlags |= MMIO_DIRTY;
if (mmioAdvance(hmmioOut, &mmioinfoOut, MMIO_WRITE) != 0)
cout<<"error write "<<endl;
}
*(mmioinfoOut.pchNext)++ =pDataEcho[2*N2-lSamples];
}
if (mmioGetInfo(hmmioOut, &mmioinfoOut, 0) != 0)
cout<<"error writing data in file "<<endl;
ckOut.cksize = sizeof(pcmWaveFormat)*10;
mmioinfoOut.dwFlags |= MMIO_DIRTY;
if (mmioSetInfo(hmmioOut, &mmioinfoOut, 0) != 0)
cout<<"error end "<<endl;
if (mmioAscend(hmmioOut, &ckOut, 0) != 0)
cout<<"error end "<<endl;
if (mmioAscend(hmmioOut, &ckOutRIFF, 0) != 0)
cout<<"error end "<<endl;
if (hmmioOut != NULL)
mmioClose(hmmioOut, 0);