Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Мультимедия, OpenGL/DirectX > Bass. Запись голоса под музыку.


Автор: Dronchik 28.12.2008, 16:29
Приветствую всех форумчан! Сейчас работаю над одной программой. Программа для записи, обработки звука. Использую звуковую библиотеку Bass вместе с Bass fx. Сейчас делаю возможность записывать голос под музыку. Столкнулся с проблемой при сохранении голосового потока в wav файл. Проблема возникает если в программу загружена музыка. Музыку загружаю так:
Код

BASS_StreamFree(chan); // free the old stream
chan=BASS_StreamCreateFile(FALSE,file,0,0,BASS_STREAM_DECODE); //chan типа HSTREAM
if (!chan) chan=BASS_MusicLoad(FALSE, file, 0, 0, BASS_MUSIC_RAMP|BASS_MUSIC_PRESCAN|BASS_STREAM_DECODE,0);                        

// get the current sample rate
BASS_ChannelGetAttribute(chan, BASS_ATTRIB_FREQ, &freq);
oldfreq = freq;

// create a new stream - decoded & resampled :)
if (!(chan=BASS_FX_TempoCreate(chan, BASS_SAMPLE_LOOP|BASS_FX_FREESOURCE)))
{    
    Error("Couldn't create a resampled stream!");
    BASS_StreamFree(chan);
    BASS_MusicFree(chan);                        
}

Звук записываю так:
Код

#define BUFSTEP 1500000    // memory allocation unit

int input;                // current input source
char *recbuf=NULL;        // recording buffer
DWORD reclen;            // recording length

HRECORD rvoice=0;        // recording channel
HSTREAM voice=0;            // playback channel
float level=100;

//...........................................................................................

// display error messages
void Error(const char *es)
{
    char mes[200];
    sprintf(mes,"%s\n(error code: %d)",es,BASS_ErrorGetCode());
    MessageBox(win,mes,0,0);
}

//...........................................................................................

// buffer the recorded data
BOOL CALLBACK RecordingCallback(HRECORD handle, const void *buffer, DWORD length, void *user)
{
    // increase buffer size if needed
    if ((reclen%BUFSTEP)+length>=BUFSTEP) {
        recbuf=realloc(recbuf,((reclen+length)/BUFSTEP+1)*BUFSTEP);
        if (!recbuf) {
            rvoice=0;
            Error("Out of memory!");
            MESS(IDB_RECORD_VOICE,WM_SETTEXT,0,"Record voice");
            return FALSE; // stop recording
        }
    }
    // buffer the data
    memcpy(recbuf+reclen,buffer,length);
    reclen+=length;
    return TRUE; // continue recording
}

void StartRecording()
{
    WAVEFORMATEX *wf;
    if (recbuf) { // free old recording
        BASS_StreamFree(voice);
        BASS_MusicFree(voice);    
        voice=0;
        free(recbuf);
        recbuf=NULL;
        EnableWindow(DLGITEM(IDC_PLAY_VOICE),FALSE);        
        // close output device before recording incase of half-duplex device
        //BASS_Free();
    }
    // allocate initial buffer and make space for WAVE header
    recbuf=malloc(BUFSTEP);
    reclen=44;
    // fill the WAVE header
    memcpy(recbuf,"RIFF\0\0\0\0WAVEfmt \20\0\0\0",20);
    memcpy(recbuf+36,"data\0\0\0\0",8);
    wf=(WAVEFORMATEX*)(recbuf+20);
    wf->wFormatTag=1;
    wf->nChannels=2;
    wf->wBitsPerSample=16;
    wf->nSamplesPerSec=44100;
    wf->nBlockAlign=wf->nChannels*wf->wBitsPerSample/8;
    wf->nAvgBytesPerSec=wf->nSamplesPerSec*wf->nBlockAlign;
    // start recording @ 44100hz 16-bit stereo
    if (!(rvoice=BASS_RecordStart(44100,2,0,&RecordingCallback,0))) {
        Error("Couldn't start recording");
        free(recbuf);
        recbuf=0;
        return;
    }
    MESS(IDB_RECORD_VOICE,WM_SETTEXT,0,"Stop recording");
}

void StopRecording()
{
    BASS_ChannelStop(rvoice);
    BASS_StreamFree(voice); // free the old stream
    rvoice=0;
    MESS(IDB_RECORD_VOICE,WM_SETTEXT,0,"Record voice");
    // complete the WAVE header
    *(DWORD*)(recbuf+4)=reclen-8;
    *(DWORD*)(recbuf+40)=reclen-44;    
        
    ofnv.lStructSize=sizeof(ofnv);    
    ofnv.hwndOwner=win;    
    ofnv.nMaxFile=MAX_PATH;
    ofnv.lpstrFile=v_file;    
    ofnv.Flags=OFN_HIDEREADONLY|OFN_EXPLORER;
    ofnv.lpstrFilter="WAV files\0*.wav\0All files\0*.*\0\0";
    ofnv.lpstrDefExt="wav";    
    
    fpv=fopen(v_file,"wb");        
    fwrite(recbuf,reclen,1,fpv); //вот эта строчка сносит программу.    
    fclose(fpv);    

    
    // create a stream from the recording
    if(voice=BASS_StreamCreateFile(FALSE,"media/voice.wav",0,0,BASS_STREAM_DECODE))
    {
        if(!voice) voice=BASS_MusicLoad(FALSE, "media/voice.wav", 0, 0, 
            BASS_MUSIC_RAMP|BASS_MUSIC_PRESCAN|BASS_STREAM_DECODE,0);
        EnableWindow(DLGITEM(IDC_PLAY_VOICE),TRUE); // enable "play" button
    }
    else
        EnableWindow(DLGITEM(IDC_PLAY_VOICE),TRUE); // enable "play" button

    // get the current sample rate
    BASS_ChannelGetAttribute(voice, BASS_ATTRIB_FREQ, &v_freq);
    v_oldfreq = v_freq;

    // create a new stream - decoded & resampled :)
    if (!(voice=BASS_FX_TempoCreate(voice, BASS_SAMPLE_LOOP|BASS_FX_FREESOURCE)))
    {
        //MESS(ID_OPEN,WM_SETTEXT,0,"click here to open a file && play it...");
        Error("Couldn't create a resampled stream!");
        BASS_StreamFree(voice);
        BASS_MusicFree(voice);        
    }

    //BASS_Free();
    
}

Инициализация и девайса записи и самого bass проходит под одним ид, иначе программа ругается на невозможность инициализации девайса записи.
Код

// initialize default output device
if (!BASS_Init(-1,44100,0,win,NULL)) 
{
    Error("Can't initialize device");
    DestroyWindow(win);
}

//.......................................................................

if (!BASS_RecordInit(-1)) 
{
    Error("Can't initialize recording device");
    DestroyWindow(win);
}

BASS_RecordSetInput(BASS_INPUT_TYPE_MIC,0,level); // get info on the input

Вылет программы происходит на указанной коментарием строчке во втором листинге. Не могу понять почему программа рушится и вылетает с предложением отправить отчёт. В чём проблема? 
ЗЫ: звук записывается через микрофон. Программа рушится при вызове функции StopRecording().

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)