This sample app demonstrates how to use the audio APIs for transcoding audio samples.
1. Get the AudioFactory instance
auto &audioFactory = AudioFactory::getInstance();
2. Get the AudioManager instance and check for audio subsystem readiness
std::promise<ServiceStatus> prom{};
audioManager = audioFactory.getAudioManager([&prom](ServiceStatus serviceStatus) {
prom.set_value(serviceStatus);
});
if (!audioManager) {
std::cout << "Failed to get AudioManager object" << std::endl;
return;
}
ServiceStatus managerStatus = audioManager->getServiceStatus();
if (managerStatus != ServiceStatus::SERVICE_AVAILABLE) {
std::cout << "\nAudio subsystem is not ready, Please wait ..." << std::endl;
managerStatus = prom.get_future().get();
}
if (managerStatus == ServiceStatus::SERVICE_AVAILABLE) {
std::cout << "Audio Subsytem is Ready << std::endl;
} else {
std::cout << "ERROR - Unable to initialize audio subsystem" << std::endl;
return;
}
3. Create an audio transcoder
FormatInfo inputConfig_;
FormatInfo outputConfig_;
AmrwbpParams inputParams{};
inputConfig_.sampleRate = SAMPLE_RATE;
inputConfig_.mask = CHANNEL_MASK;
inputConfig_.format = AudioFormat::AMRWB_PLUS;
inputParams.bitWidth = 16;
inputParams.frameFormat = AmrwbpFrameFormat::FILE_STORAGE_FORMAT;
inputConfig_.params = &inputParams;
inputConfig_.sampleRate = SAMPLE_RATE;
outputConfig_.mask = CHANNEL_MASK;
outputConfig_.format = AudioFormat::PCM_16BIT_SIGNED;
outputConfig_.params = nullptr;
audioManager->createTranscoder(inputConfig_, outputConfig_,
[&p,this](std::shared_ptr<telux::audio::ITranscoder> &transcoder,
telux::common::ErrorCode error) {
if (error == telux::common::ErrorCode::SUCCESS) {
transcoder_ = transcoder;
registerListener();
p.set_value(true);
} else {
p.set_value(false);
std::cout << "failed to create transcoder" <<std::endl;
}
});
if (p.get_future().get()) {
std::cout<< "Transcoder Created" << std::endl;
}
4.1 Allocate audio buffers for write operation
auto audioBuffer = transcoder_->getWriteBuffer();
if (audioBuffer != nullptr) {
size = audioBuffer->getMinSize();
if (size == 0) {
size = audioBuffer->getMaxSize();
}
audioBuffer->setDataSize(size);
} else {
std::cout << "Failed to get Audio Buffer for write operation " << std::endl;
}
4.2 Allocate audio buffers for read operation
auto audioBuffer = transcoder_->getReadBuffer();
if (audioBuffer != nullptr) {
size = audioBuffer->getMinSize();
if (size == 0) {
size = audioBuffer->getMaxSize();
}
audioBuffer->setDataSize(size);
} else {
std::cout << "Failed to get Audio Buffer for read operation " << std::endl;
}
5. Start write operation in one thread for transcoding
void writeCallback(std::shared_ptr<IAudioBuffer> buffer,
uint32_t bytes, ErrorCode error) {
std::cout << "Bytes Written : " << bytes << std::endl;
if (error != ErrorCode::SUCCESS || buffer->getDataSize() != bytes) {
pipeLineEmpty_ = false;
}
buffer->reset();
writeBuffers_.push(buffer);
cv_.notify_all();
return;
}
void onReadyForWrite() {
pipeLineEmpty_ = true;
}
auto writeCb = std::bind(&TranscoderApp::writeCallback, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3);
telux::common::Status status = telux::common::Status::FAILED;
if (EOF_REACHED) {
status = transcoder_->write(audioBuffer, EOF_REACHED, writeCb);
} else {
status = transcoder_->write(audioBuffer, EOF_NOT_REACHED, writeCb);
}
if (status != telux::common::Status::SUCCESS) {
std::cout << "write() failed with error" << static_cast<unsigned int>(status) << std::endl;
} else {
std::cout << "Request to transcode buffers sent " << std::endl;
}
6. Start read operation in another thread for transcoding
void readCallback(std::shared_ptr<telux::audio::IAudioBuffer> buffer,
uint32_t isLastBuffer, telux::common::ErrorCode error) {
if (isLastBuffer) {
}
if (error != telux::common::ErrorCode::SUCCESS) {
std::cout << "read() returned with error " << static_cast<unsigned int>(error)
<< std::endl;
} else {
}
buffer->reset();
readBuffers_.push(buffer);
cv_.notify_all();
return;
}
auto readCb = std::bind(&TranscoderApp::readCallback, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
telux::common::Status status = transcoder_->read(audioBuffer, bytesToRead, readCb);
if (status != telux::common::Status::SUCCESS) {
std::cout << "read() failed with error" << static_cast<unsigned int>(status) << std::endl;
}
7. Tear down the audio transcoder instance
std::promise<bool> p;
auto status = transcoder_->tearDown([&p](telux::common::ErrorCode error) {
if (error == telux::common::ErrorCode::SUCCESS) {
p.set_value(true);
} else {
p.set_value(false);
std::cout << "Failed to tear down" << std::endl;
}
});
if (status == telux::common::Status::SUCCESS) {
std::cout << "Request to Teardown transcoder sent" << std::endl;
} else {
std::cout << "Request to Teardown transcoder failed" << std::endl;
}
if (p.get_future().get()) {
transcoder_ = nullptr;
std::cout << "Tear Down successful !!" << std::endl;
}