void AlsaLayer::playback(int maxFrames) { unsigned framesToGet = Manager::instance().getMainBuffer().availableForGet(MainBuffer::DEFAULT_ID); // no audio available, play tone or silence if (framesToGet <= 0) { // FIXME: not thread safe! we only lock the mutex when we get the // pointer, we have no guarantee that it will stay safe to use AudioLoop *tone = Manager::instance().getTelephoneTone(); AudioLoop *file_tone = Manager::instance().getTelephoneFile(); playbackBuff_.setFormat(audioFormat_); playbackBuff_.resize(maxFrames); if (tone) tone->getNext(playbackBuff_, playbackGain_); else if (file_tone && !ringtoneHandle_) file_tone->getNext(playbackBuff_, playbackGain_); else playbackBuff_.reset(); playbackBuff_.interleave(playbackIBuff_); write(playbackIBuff_.data(), playbackBuff_.frames(), playbackHandle_); } else { // play the regular sound samples const AudioFormat mainBufferFormat = Manager::instance().getMainBuffer().getInternalAudioFormat(); const bool resample = audioFormat_.sample_rate != mainBufferFormat.sample_rate; double resampleFactor = 1.0; unsigned maxNbFramesToGet = maxFrames; if (resample) { resampleFactor = static_cast<double>(audioFormat_.sample_rate) / mainBufferFormat.sample_rate; maxNbFramesToGet = maxFrames / resampleFactor; } framesToGet = std::min(framesToGet, maxNbFramesToGet); playbackBuff_.setFormat(mainBufferFormat); playbackBuff_.resize(framesToGet); Manager::instance().getMainBuffer().getData(playbackBuff_, MainBuffer::DEFAULT_ID); playbackBuff_.applyGain(isPlaybackMuted_ ? 0.0 : playbackGain_); if (audioFormat_.nb_channels != mainBufferFormat.nb_channels) { playbackBuff_.setChannelNum(audioFormat_.nb_channels, true); } if (resample) { const size_t outFrames = framesToGet * resampleFactor; AudioBuffer rsmpl_out(outFrames, audioFormat_); resampler_.resample(playbackBuff_, rsmpl_out); rsmpl_out.interleave(playbackIBuff_); write(playbackIBuff_.data(), outFrames, playbackHandle_); } else { playbackBuff_.interleave(playbackIBuff_); write(playbackIBuff_.data(), framesToGet, playbackHandle_); } } }
void JackLayer::fillWithToneOrRingtone(AudioBuffer &buffer) { buffer.resize(hardwareBufferSize_); AudioLoop *tone = Manager::instance().getTelephoneTone(); AudioLoop *file_tone = Manager::instance().getTelephoneFile(); // In case of a dtmf, the pointers will be set to nullptr once the dtmf length is // reached. For this reason we need to fill audio buffer with zeros if pointer is nullptr if (tone) { tone->getNext(buffer, playbackGain_); } else if (file_tone) { file_tone->getNext(buffer, playbackGain_); } else { buffer.reset(); } }