void AudioThread::setActive(bool state) { AudioThreadInput *dummy; if (state && !active && inputQueue) { while (!inputQueue->empty()) { // flush queue inputQueue->pop(dummy); if (dummy) { dummy->decRefCount(); } } deviceController[parameters.deviceId]->bindThread(this); } else if (!state && active) { deviceController[parameters.deviceId]->removeThread(this); if(inputQueue) { while (!inputQueue->empty()) { // flush queue inputQueue->pop(dummy); if (dummy) { dummy->decRefCount(); } } } } active = state; }
void DemodulatorThread::run() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread int priority = sched_get_priority_max( SCHED_FIFO )-1; sched_param prio = {priority}; // scheduling priority of thread pthread_setschedparam(tID, SCHED_FIFO, &prio); #endif ReBuffer<AudioThreadInput> audioVisBuffers; std::cout << "Demodulator thread started.." << std::endl; iqInputQueue = (DemodulatorThreadPostInputQueue*)getInputQueue("IQDataInput"); audioOutputQueue = (AudioThreadInputQueue*)getOutputQueue("AudioDataOutput"); threadQueueControl = (DemodulatorThreadControlCommandQueue *)getInputQueue("ControlQueue"); threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue"); ModemIQData modemData; while (!terminated) { DemodulatorThreadPostIQData *inp; iqInputQueue->pop(inp); // std::lock_guard < std::mutex > lock(inp->m_mutex); audioSampleRate = demodInstance->getAudioSampleRate(); int bufSize = inp->data.size(); if (!bufSize) { inp->decRefCount(); continue; } if (inp->modemKit && inp->modemKit != cModemKit) { if (cModemKit != nullptr) { cModem->disposeKit(cModemKit); } cModemKit = inp->modemKit; } if (inp->modem && inp->modem != cModem) { delete cModem; cModem = inp->modem; } if (!cModem || !cModemKit) { inp->decRefCount(); continue; } float currentSignalLevel = 0; float accum = 0; for (std::vector<liquid_float_complex>::iterator i = inp->data.begin(); i != inp->data.end(); i++) { accum += abMagnitude(0.948059448969, 0.392699081699, i->real, i->imag); } currentSignalLevel = linearToDb(accum / float(inp->data.size())); if (currentSignalLevel < DEMOD_SIGNAL_MIN+1) { currentSignalLevel = DEMOD_SIGNAL_MIN+1; } std::vector<liquid_float_complex> *inputData; inputData = &inp->data; modemData.sampleRate = inp->sampleRate; modemData.data.assign(inputData->begin(), inputData->end()); modemData.setRefCount(1); AudioThreadInput *ati = NULL; ModemAnalog *modemAnalog = (cModem->getType() == "analog")?((ModemAnalog *)cModem):nullptr; // ModemDigital *modemDigital = (cModem->getType() == "digital")?((ModemDigital *)cModem):nullptr; if (modemAnalog != nullptr) { ati = outputBuffers.getBuffer(); ati->sampleRate = audioSampleRate; ati->inputRate = inp->sampleRate; ati->setRefCount(1); } cModem->demodulate(cModemKit, &modemData, ati); if (currentSignalLevel > signalLevel) { signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.5; } else { signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.05; } bool squelched = (squelchEnabled && (signalLevel < squelchLevel)); if (audioOutputQueue != NULL && ati && !squelched) { std::vector<float>::iterator data_i; ati->peak = 0; for (data_i = ati->data.begin(); data_i != ati->data.end(); data_i++) { float p = fabs(*data_i); if (p > ati->peak) { ati->peak = p; } } } else if (ati) { ati->decRefCount(); ati = nullptr; } if (ati && audioVisOutputQueue != NULL && audioVisOutputQueue->empty()) { AudioThreadInput *ati_vis = audioVisBuffers.getBuffer(); ati_vis->setRefCount(1); ati_vis->sampleRate = inp->sampleRate; ati_vis->inputRate = inp->sampleRate; int num_vis = DEMOD_VIS_SIZE; if (ati->channels==2) { ati_vis->channels = 2; int stereoSize = ati->data.size(); if (stereoSize > DEMOD_VIS_SIZE * 2) { stereoSize = DEMOD_VIS_SIZE * 2; } ati_vis->data.resize(stereoSize); if (inp->modemType == "I/Q") { for (int i = 0; i < stereoSize / 2; i++) { ati_vis->data[i] = (*inputData)[i].real * 0.75; ati_vis->data[i + stereoSize / 2] = (*inputData)[i].imag * 0.75; } } else { for (int i = 0; i < stereoSize / 2; i++) { ati_vis->inputRate = audioSampleRate; ati_vis->sampleRate = 36000; ati_vis->data[i] = ati->data[i * 2]; ati_vis->data[i + stereoSize / 2] = ati->data[i * 2 + 1]; } } } else { int numAudioWritten = ati->data.size(); ati_vis->channels = 1; std::vector<float> *demodOutData = (modemAnalog != nullptr)?modemAnalog->getDemodOutputData():nullptr; if ((numAudioWritten > bufSize) || (demodOutData == nullptr)) { ati_vis->inputRate = audioSampleRate; if (num_vis > numAudioWritten) { num_vis = numAudioWritten; } ati_vis->data.assign(ati->data.begin(), ati->data.begin() + num_vis); } else { if (num_vis > demodOutData->size()) { num_vis = demodOutData->size(); } ati_vis->data.assign(demodOutData->begin(), demodOutData->begin() + num_vis); } } audioVisOutputQueue->push(ati_vis); } if (ati != NULL) { if (!muted.load()) { audioOutputQueue->push(ati); } else { ati->setRefCount(0); } } if (!threadQueueControl->empty()) { while (!threadQueueControl->empty()) { DemodulatorThreadControlCommand command; threadQueueControl->pop(command); switch (command.cmd) { case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_ON: squelchEnabled = true; break; case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_OFF: squelchEnabled = false; break; default: break; } } } inp->decRefCount(); } // end while !terminated outputBuffers.purge(); if (audioVisOutputQueue && !audioVisOutputQueue->empty()) { AudioThreadInput *dummy_vis; audioVisOutputQueue->pop(dummy_vis); } audioVisBuffers.purge(); DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED); tCmd.context = this; threadQueueNotify->push(tCmd); std::cout << "Demodulator thread done." << std::endl; }
void AudioThread::run() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread int priority = sched_get_priority_max( SCHED_RR) - 1; sched_param prio = {priority}; // scheduling priority of thread pthread_setschedparam(tID, SCHED_RR, &prio); #endif // std::cout << "Audio thread initializing.." << std::endl; if (dac.getDeviceCount() < 1) { std::cout << "No audio devices found!" << std::endl; return; } setupDevice((outputDevice.load() == -1) ? (dac.getDefaultOutputDevice()) : outputDevice.load()); // std::cout << "Audio thread started." << std::endl; inputQueue = static_cast<AudioThreadInputQueue *>(getInputQueue("AudioDataInput")); threadQueueNotify = static_cast<DemodulatorThreadCommandQueue*>(getOutputQueue("NotifyQueue")); while (!terminated) { AudioThreadCommand command; cmdQueue.pop(command); if (command.cmd == AudioThreadCommand::AUDIO_THREAD_CMD_SET_DEVICE) { setupDevice(command.int_value); } if (command.cmd == AudioThreadCommand::AUDIO_THREAD_CMD_SET_SAMPLE_RATE) { setSampleRate(command.int_value); } } // Drain any remaining inputs if (inputQueue) while (!inputQueue->empty()) { AudioThreadInput *ref; inputQueue->pop(ref); if (ref) { ref->decRefCount(); } } if (currentInput) { currentInput->setRefCount(0); currentInput = nullptr; } if (deviceController[parameters.deviceId] != this) { deviceController[parameters.deviceId]->removeThread(this); } else { try { if (dac.isStreamOpen()) { if (dac.isStreamRunning()) { dac.stopStream(); } dac.closeStream(); } } catch (RtAudioError& e) { e.printMessage(); } } if (threadQueueNotify != NULL) { DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_AUDIO_TERMINATED); tCmd.context = this; threadQueueNotify->push(tCmd); } // std::cout << "Audio thread done." << std::endl; }