void SoundInput::handleStateChanged (QAudio::State newState) const { // qDebug () << "SoundInput::handleStateChanged: newState:" << newState; switch (newState) { case QAudio::IdleState: Q_EMIT status (tr ("Idle")); break; case QAudio::ActiveState: Q_EMIT status (tr ("Receiving")); break; case QAudio::SuspendedState: Q_EMIT status (tr ("Suspended")); break; case QAudio::StoppedState: if (audioError ()) { Q_EMIT status (tr ("Error")); } else { Q_EMIT status (tr ("Stopped")); } break; } }
void SoundInput::start(QAudioDeviceInfo const& device, int framesPerBuffer, AudioDevice * sink, unsigned downSampleFactor, AudioDevice::Channel channel) { Q_ASSERT (sink); stop (); m_sink = sink; QAudioFormat format (device.preferredFormat()); format.setChannelCount (AudioDevice::Mono == channel ? 1 : 2); format.setCodec ("audio/pcm"); format.setSampleRate (12000 * downSampleFactor); format.setSampleType (QAudioFormat::SignedInt); format.setSampleSize (16); if (!format.isValid ()) { Q_EMIT error (tr ("Requested input audio format is not valid.")); return; } // this function lies! // if (!device.isFormatSupported (format)) // { // Q_EMIT error (tr ("Requested input audio format is not supported on device.")); // return; // } m_stream.reset (new QAudioInput {device, format}); if (audioError ()) { return; } connect (m_stream.data(), &QAudioInput::stateChanged, this, &SoundInput::handleStateChanged); m_stream->setBufferSize (m_stream->format ().bytesForFrames (framesPerBuffer)); if (sink->initialize (QIODevice::WriteOnly, channel)) { m_stream->start (sink); audioError (); } else { Q_EMIT error (tr ("Failed to initialize audio sink device")); } }
void SoundInput::suspend () { if (m_stream) { m_stream->suspend (); audioError (); } }
void SoundInput::resume () { if (m_sink) { m_sink->reset (); } if (m_stream) { m_stream->resume (); audioError (); } }
void initWinMM(void) { WAVEFORMATEX wfe; // Format of the mixing buffers we will be sending to the audio hardware to play MMRESULT mmr; // Temporary container to hold the result of Multimedia function calls audioLog->log("Initializing WinMM Sound System"); int numDevs = waveOutGetNumDevs(); // Retrieve the number of multimedia sound playing devices in the system audioLog->log("%i WaveOut devices detected\n",numDevs); if (numDevs==0) return; // No audio devices detected, or an error occured audioNumSpeakers = 2; WinMM_mixFreq = 44100; uint16 sampleSize = 2 * audioNumSpeakers; // 16 bit stereo (16 bits * number of speakers) bufferSizeBytes = WinMM_mixFreq*sampleSize*BUFFERSIZE/1000; // Calculate the size of the buffers in BYTES bufferSizeSamples = WinMM_mixFreq*BUFFERSIZE/1000; // Calculate the size of the buffers in SAMPLES initSWAudioMixer(WinMM_mixFreq,bufferSizeSamples,16,audioNumSpeakers); wfe.wFormatTag = WAVE_FORMAT_PCM; // We are genertating uncompressed Pulse-Code Modulation ... wfe.nChannels = audioNumSpeakers; // In stereo (2 channels) wfe.nSamplesPerSec=WinMM_mixFreq; // at 44 Khz wfe.nAvgBytesPerSec=WinMM_mixFreq * sampleSize; // Consuming 44100 * 4 bytes per second wfe.nBlockAlign=sampleSize; // 1 block = size of each sample * number of channels wfe.wBitsPerSample=16; // 16 bit audio wfe.cbSize=0; // size of extensible data ... plain PCM is fine, no extensible data needed // Open a handle to the WaveOut device (like files, we must open a device before accessing it) mmr=waveOutOpen( &WinMM_hwaveout, // &hwaveout points to where we want to store the handle to the WaveOut device WAVE_MAPPER, // We want the system's DEFAULT playback device (you should ALWAYS use this device) &wfe, // Points to the format description of the sound we will be playing (DWORD_PTR)WinMM_CallBack, // Points to the function to call when we finish playing a buffer 0, // A number we send to the callback function, can be anything we like CALLBACK_FUNCTION); // What special features of playback do we require ... only one: call our callback function if (mmr!=MMSYSERR_NOERROR) { audioError("waveOutOpen",mmr); // Report any error that occured return; } byte *tmp = (byte *)fcalloc(bufferSizeBytes*2,"WinMM Audio Buffers"); for (int i=0; i<2; i++) // For each buffer (there will only ever be 2 buffers) { WinMM_buffer[i] = tmp + bufferSizeBytes * i; // Allocate memory for buffer memfill(WinMM_buffer[i], 0, bufferSizeBytes); // Fill the buffer with silence WinMM_header[i].lpData = (LPSTR)WinMM_buffer[i]; // Tell the header where the buffer is located WinMM_header[i].dwBufferLength = bufferSizeBytes; // Tell the header the size of the buffer mmr=waveOutPrepareHeader(WinMM_hwaveout,&WinMM_header[i],sizeof(WAVEHDR)); // Prepare the header (Make the sound system aware that it will need to play this type of sound) if (mmr!=MMSYSERR_NOERROR) { audioError("waveOutOpen",mmr); // Report any errors return; } } nextBuffer=0; // The next buffer to process is buffer #0 audioSemaphore = 0; // Tell the system it's save to receive hardware interrupts // Force sound system to start playing sounds (Sound begins playing the moment the first buffer is written to the device) mmr=waveOutWrite(WinMM_hwaveout,&WinMM_header[0],sizeof(WAVEHDR)); // Write the first buffer (will be silent) if (mmr!=MMSYSERR_NOERROR) { audioError("waveOutWrite",mmr); // Report any errors return; } mmr=waveOutWrite(WinMM_hwaveout,&WinMM_header[1],sizeof(WAVEHDR)); // Write the second buffer (will be silent) if (mmr!=MMSYSERR_NOERROR) { audioError("waveOutWrite",mmr); // Report any errors return; } }