новые иконки в OpenBoard
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
OpenBoard/src/podcast/windowsmedia/UBWaveRecorder.cpp

263 lines
6.5 KiB

/*
* Copyright (C) 2013 Open Education Foundation
*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour
* l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of OpenBoard.
*
* OpenBoard is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License,
* with a specific linking exception for the OpenSSL project's
* "OpenSSL" library (or with modified versions of it that use the
* same license as the "OpenSSL" library).
*
* OpenBoard is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenBoard. If not, see <http://www.gnu.org/licenses/>.
*/
#include "UBWaveRecorder.h"
#include "Mmsystem.h"
#include "core/memcheck.h"
UBWaveRecorder::UBWaveRecorder(QObject * pParent)
: QObject(pParent)
, mIsRecording(false)
, mMsTimeStamp(0)
, mBufferLengthInMs(100)
, mNbChannels(2)
, mSampleRate(44100)
, mBitsPerSample(16)
{
// NOOP
}
UBWaveRecorder::~UBWaveRecorder()
{
// NOOP
}
bool UBWaveRecorder::init(const QString& waveInDeviceName)
{
UINT deviceID = WAVE_MAPPER;
if (waveInDeviceName.length() > 0)
{
int count = waveInGetNumDevs();
WAVEINCAPS caps;
for (int i = 0; i < count; i++)
{
if (waveInGetDevCaps(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR)
{
QString deviceName = QString:: fromUtf16(caps.szPname);
if (deviceName == waveInDeviceName)
{
deviceID = i;
break;
}
}
}
}
WAVEFORMATEX format;
format.cbSize = 0;
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = mNbChannels;
format.wBitsPerSample = mBitsPerSample;
format.nSamplesPerSec = mSampleRate;
format.nBlockAlign = format.nChannels * (format.wBitsPerSample / 8);
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
if (waveInOpen(&mWaveInDevice, deviceID, &format, (DWORD)waveInProc, (DWORD_PTR)this, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
{
setLastErrorMessage("Cannot open wave in device ");
return false;
}
int nbBuffers = 6;
int sampleBufferSize = 44100 * 2 * 2 * mBufferLengthInMs / 1000; // 44.1 Khz * stereo * 16bit * buffer length
for (int i = 0; i < nbBuffers; i++)
{
WAVEHDR* buffer = new WAVEHDR();
ZeroMemory(buffer, sizeof(WAVEHDR));
buffer->lpData = (LPSTR)new BYTE[sampleBufferSize];
ZeroMemory(buffer->lpData, sampleBufferSize);
buffer->dwBufferLength = sampleBufferSize;
buffer->dwFlags = 0;
if (waveInPrepareHeader(mWaveInDevice, buffer, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
{
setLastErrorMessage("Cannot prepare wave header");
return false;
}
if (waveInAddBuffer(mWaveInDevice, buffer, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
{
setLastErrorMessage("Cannot add buffer");
return false;
}
mWaveBuffers << buffer;
}
return true;
}
bool UBWaveRecorder::start()
{
if (!mIsRecording)
{
mRecordingStartTime = QTime::currentTime();
mMsTimeStamp = 0;
mIsRecording = true;
}
if (waveInStart(mWaveInDevice) != MMSYSERR_NOERROR)
{
setLastErrorMessage("Cannot start wave in device ");
return false;
}
return true;
}
bool UBWaveRecorder::stop()
{
mIsRecording = false;
if (waveInStop(mWaveInDevice) != MMSYSERR_NOERROR)
{
setLastErrorMessage("Cannot stop wave in device ");
return false;
}
return true;
}
bool UBWaveRecorder::close()
{
if (waveInReset(mWaveInDevice) != MMSYSERR_NOERROR)
{
setLastErrorMessage("Cannot reset wave in device ");
return false;
}
foreach(WAVEHDR* buffer, mWaveBuffers)
{
waveInUnprepareHeader(mWaveInDevice, buffer, sizeof(WAVEHDR));
delete [] buffer->lpData;
delete buffer;
}
mWaveBuffers.clear();
if (waveInClose(mWaveInDevice) != MMSYSERR_NOERROR)
{
setLastErrorMessage("Cannot close wave in device ");
return false;
}
return true;
}
void CALLBACK UBWaveRecorder::waveInProc(HWAVEIN waveInDevice, UINT message, DWORD_PTR instance,
DWORD_PTR param1, DWORD_PTR param2)
{
Q_UNUSED(param2);
if (message == WIM_DATA)
{
//qDebug() << "wave in receiving data";
UBWaveRecorder* recorder = (UBWaveRecorder*)instance;
WAVEHDR *buffer = (WAVEHDR *)param1;
if (recorder && buffer && recorder->isRecording())
{
waveInUnprepareHeader(waveInDevice, buffer, sizeof(WAVEHDR));
recorder->emitNewWaveBuffer(buffer);
if (waveInPrepareHeader(waveInDevice, buffer, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
{
recorder->setLastErrorMessage("Cannot recycle wave header");
}
if (waveInAddBuffer(waveInDevice, buffer, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
{
recorder->setLastErrorMessage("Cannot recycle buffer");
}
}
}
}
void UBWaveRecorder::emitNewWaveBuffer(WAVEHDR * pBuffer)
{
if (mIsRecording)
{
emit newWaveBuffer(pBuffer, mMsTimeStamp);
long bufferMs = pBuffer->dwBytesRecorded / mNbChannels / (mBitsPerSample / 8) * 1000 / mSampleRate;
mMsTimeStamp += bufferMs;
}
}
QStringList UBWaveRecorder::waveInDevices()
{
QStringList devices;
int count = waveInGetNumDevs();
WAVEINCAPS caps;
for (int i = 0; i < count; i++)
{
if (waveInGetDevCaps(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR)
{
devices << QString::fromUtf16(caps.szPname);
}
else
{
qDebug() << "Cannot get wave in device " + QString("%1").arg(i) + " capacities";
}
}
int mixersCount = mixerGetNumDevs();
for(int i = 0; i < mixersCount; i++)
{
MIXERCAPS caps;
if (mixerGetDevCaps(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR)
{
qDebug() << "Mixer: " << QString::fromUtf16(caps.szPname);
}
}
return devices;
}