Всем привет! Пытаюсь реализовать полноценную запись/воспроизведение звука. Не получается =(
Исходные тексты прилагаются, укажите, пожалуйста, на ошибки (как работы с потоками, так и с библиотекой OpenAL) и посоветуйте как реализовать паузу во время проигрывания звукового сигнала.
файл threadal.h
C++ (Qt)
#ifndef THREADAL_H
#define THREADAL_H
#include <QThread>
#include <QTimer>
#include <QVector>
#include <al.h>
#include <alc.h>
class threadAl : public QThread {
Q_OBJECT;
public:
threadAl( qint32 s, qint16 b );
void startRecord( QVector<quint8> * pntr );
void startRecord( QVector<qint16> * pntr );
void record( );
void play( );
void playSound( QVector<quint8> * pntr );
void playSound( QVector<qint16> * pntr );
void pause( );
void stop( );
void run( );
//private slots:
// void slotNextValueTimer( );
//signals :
// void currentValueTimer( int );
private:
volatile bool recordFlag, pauseFlag, playFlag;
volatile bool mono8, mono16;
qint32 samples;
QVector<quint8> * dataPointer8;
QVector<qint16> * dataPointer16;
ALCdevice* pDev;
int bufferSize;
QTimer * timer;
unsigned int valueTimer;
};
#endif // THREADAL_H
файл threadal.cpp
C++ (Qt)
#include "threadal.h"
threadAl::threadAl( qint32 s, qint16 b ) {
samples = s;
if( b == 8 ) {
mono8 = true;
mono16 = false;
}
else { //if( b == 16 ) {
mono8 = false;
mono16 = true;
}
recordFlag = pauseFlag = playFlag = false;
dataPointer8 = 0;
dataPointer16 = 0;
bufferSize=4096;
valueTimer = 0;
// timer = new QTimer;
// connect( timer, SIGNAL(timeout()),
// this, SLOT(slotNextValueTimer()) );
}
void threadAl::record() {
// RECORDING IN threadAl
// timer->start(1000);
// if( pauseFlag )
// timer->stop();
if( pDev == 0 ) { recordFlag = false; }
else { alcCaptureStart(pDev); }
quint8 iTotalSamplesRecorded8 = 0;
qint16 iTotalSamplesRecorded16 = 0;
ALCint samples_recorded;
quint8 buffer8[ bufferSize/2 ];
qint16 buffer16[ bufferSize/2 ];
while( recordFlag == true ) {
if( pauseFlag != true ) {
if( mono8 ) {
for(int i=0; i<bufferSize/2; i++) { buffer8[i]=0; }
}
else if( mono16 ) {
for(int i=0; i<bufferSize/2; i++) { buffer16[i]=0; }
}
alcGetIntegerv(pDev, ALC_CAPTURE_SAMPLES, 1, &samples_recorded);
while( samples_recorded < bufferSize/2 ) {
alcGetIntegerv( pDev, ALC_CAPTURE_SAMPLES, 1, &samples_recorded );
}
if( mono8 ) {
alcCaptureSamples(pDev,buffer8+iTotalSamplesRecorded8,samples_recorded);
for(int i=0; i<bufferSize/2; ++i ) { dataPointer8->push_back( buffer8[i] ); }
}
else if( mono16 ) {
alcCaptureSamples(pDev,buffer16+iTotalSamplesRecorded16,samples_recorded);
for(int i=0; i<bufferSize/2; ++i ) { dataPointer16->push_back( buffer16[i] ); }
}
}
}
}
void threadAl::play() {
// PLAYING IN threadAl
int g_MainBufSzPlay;
if( mono8 ) { g_MainBufSzPlay = dataPointer8->size(); }
else if( mono16 ) { g_MainBufSzPlay = dataPointer16->size(); }
// ALCdevice *pDev=alcOpenDevice(NULL); // ?????????????????????????
pDev=alcOpenDevice(NULL);
if(pDev){
ALCcontext *pCont=alcCreateContext(pDev,NULL);
if(pCont){
// timer->start(1000);
alcMakeContextCurrent(pCont);
int numBuffers = g_MainBufSzPlay / (bufferSize) ;
ALuint * buffer = new ALuint[numBuffers];
alGenBuffers(numBuffers, buffer);
for( int k=0; k<numBuffers; ++k ) {
if( mono8 ) {
alBufferData(buffer[k],
AL_FORMAT_MONO8,
&((dataPointer8->constData())[bufferSize*k]),
bufferSize, samples);
}
else {
alBufferData(buffer[k],
AL_FORMAT_MONO16,
&((dataPointer16->constData())[bufferSize*k]),
bufferSize, samples/2);
}
}
ALuint source;
alGenSources(1,&source);
alSourceQueueBuffers( source, numBuffers, buffer );
alSourcePlay(source);
ALint source_state;
alGetSourcei(source,AL_SOURCE_STATE,&source_state);
while(source_state==AL_PLAYING) {
alGetSourcei(source,AL_SOURCE_STATE,&source_state);
}
alDeleteSources(1,&source);
alDeleteBuffers(numBuffers,buffer);
alcDestroyContext(pCont);
delete[] buffer;
}
alcCloseDevice(pDev);
}
// timer->stop();
}
void threadAl::run( ) {
if( recordFlag == true ) { record(); }
else if( playFlag == true ) { play(); }
}
void threadAl::playSound( QVector<quint8> * pntr ) {
recordFlag = false;
playFlag = true;
dataPointer16 = 0;
dataPointer8 = pntr;
mono16 = false;
mono8 = true;
this->start();
}
void threadAl::playSound( QVector<qint16> * pntr ) {
recordFlag = false;
playFlag = true;
dataPointer8 = 0;
dataPointer16 = pntr;
mono8 = false;
mono16 = true;
this->start();
}
void threadAl::startRecord( QVector<quint8> * pntr ) {
recordFlag = true;
playFlag = false;
dataPointer16 = 0;
dataPointer8 = pntr;
dataPointer8->clear();
mono16 = false;
mono8 = true;
pDev=alcCaptureOpenDevice(NULL,samples,AL_FORMAT_MONO8,bufferSize);
this->start();
}
void threadAl::startRecord( QVector<qint16> * pntr ) {
recordFlag = true;
playFlag = false;
dataPointer8 = 0;
dataPointer16 = pntr;
dataPointer16->clear();
mono8 = false;
mono16 = true;
pDev=alcCaptureOpenDevice(NULL,samples,AL_FORMAT_MONO16,bufferSize);
this->start();
}
void threadAl::stop( ) {
recordFlag = pauseFlag = playFlag = false;
alcCaptureStop(pDev);
alcCaptureCloseDevice(pDev);
// timer->stop();
emit(finished());
this->exit(0);
}
void threadAl::pause( ) {
if(pauseFlag) { pauseFlag = false; }
else { pauseFlag = true; /*timer->stop();*/ }
}
//void threadAl::slotNextValueTimer() {
// emit currentValueTimer( ++valueTimer );
//}
фрагмент файла, в котором это все используется (mainwindow.cpp)
C++ (Qt)
...
void MainWindow::slotRecord() {
recordFlag = true;
if( !recordthreadAl ) {
slotNew();
recordthreadAl = new threadAl( samples, bits );
if( mono8 ) { data8.clear(); recordthreadAl->startRecord( &data8 ); }
else if( mono16 ) { data16.clear(); recordthreadAl->startRecord( &data16 ); }
statusLabel->setText("Record active...");
slotParameters();
}
else { slotStop(); }
}
void MainWindow::slotStop() {
if( recordthreadAl && recordthreadAl->isRunning() ) {
recordthreadAl->stop();
recordthreadAl->exit(0);
recordthreadAl = 0;
}
statusLabel->setText("Record complete...");
slotParameters();
if( recordFlag ) { setData(); recordFlag=false; }
recordthreadAl = 0;
}
void MainWindow::slotPlay() {
if( recordthreadAl == 0 ) {
recordthreadAl = new threadAl(samples, bits);
connect( recordthreadAl, SIGNAL(finished()),
this, SLOT(slotPlayFinish()) );
if( mono8 ) { recordthreadAl->playSound( &data8 ); }
else if( mono16 ) { recordthreadAl->playSound( &data16 ); }
statusLabel->setText( "Playing now..." );
slotParameters();
}
else { slotStop(); slotPlay();}
}
void MainWindow::slotPause() { QMessageBox::information(this, "", "pause"); }
...
Заранее, очень признателен всем ответившим )