This sample app demonstrates how to use the audio APIs for compressed audio format playback on voice paths.
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 instance" << 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 playback session with voice path direction
StreamConfig config;
config.type = StreamType::PLAY;
config.slotId = DEFAULT_SLOT_ID;
config.sampleRate = SAMPLE_RATE;
config.format = AudioFormat::AMRWB_PLUS;
config.channelTypeMask = (ChannelType::LEFT | ChannelType::RIGHT);
config.voicePaths.emplace_back(Direction::TX);
AmrwbpParams amrParams{};
if (config.format == AudioFormat::AMRWB_PLUS) {
amrParams.bitWidth = 16;
amrParams.frameFormat = AmrwbpFrameFormat::FILE_STORAGE_FORMAT;
config.formatParams = &amrParams;
} else {
config.formatParams = nullptr;
}
std::promise<bool> p;
auto status = audioManager->createStream(config,
[&p,this](std::shared_ptr<IAudioStream> &audioStream, ErrorCode error) {
if (error == ErrorCode::SUCCESS) {
audioPlayStream_ = std::dynamic_pointer_cast<IAudioPlayStream>(audioStream);
p.set_value(true);
} else {
p.set_value(false);
std::cout << "failed to Create a stream" <<std::endl;
}
});
if (status == Status::SUCCESS) {
std::cout << "Request to create stream sent" << std::endl;
} else {
std::cout << "Request to create stream failed" << std::endl;
}
if (p.get_future().get()) {
std::cout<< "Audio Play Stream is Created" << std::endl;
}
4. Allocate stream buffers for playback operation
auto streamBuffer = audioPlayStream->getStreamBuffer();
if (streamBuffer != nullptr) {
size = streamBuffer->getMinSize();
if (size == 0) {
size = streamBuffer->getMaxSize();
}
streamBuffer->setDataSize(size);
} else {
std::cout << "Failed to get Stream Buffer " << std::endl;
}
5. Start write operation for playback to start
void writeCallback(std::shared_ptr<IStreamBuffer> buffer, uint32_t bytes, ErrorCode error)
{
if (error != ErrorCode::SUCCESS) {
std::cout << "write() returned with error " << static_cast<int>(error) << std::endl;
pipeLineEmpty_ = false;
}
buffer->reset();
return;
}
void onReadyForWrite() {
pipeLineEmpty_ = true;
}
memset(streamBuffer->getRawBuffer(),0x1,size);
auto status = audioPlayStream->write(streamBuffer, writeCallback);
if (status != telux::common::Status::SUCCESS) {
std::cout << "write() failed with error" << static_cast<int>(status) << std::endl;
} else {
std::cout << "Request to write to stream sent" << std::endl;
}
6.1 Stop playback operation(STOP_AFTER_PLAY : Stops after playing pending buffers in pipeline)
std::promise<bool> p;
auto status = audioPlayStream_->stopAudio(StopType::STOP_AFTER_PLAY, [&p](ErrorCode error) {
if (error == ErrorCode::SUCCESS) {
p.set_value(true);
} else {
p.set_value(false);
std::cout << "Failed to stop after playing buffers" << std::endl;
}
});
if (status == Status::SUCCESS) {
std::cout << "Request to stop playback after pending buffers Sent" << std::endl;
} else {
std::cout << "Request to stop playback after pending buffers failed" << std::endl;
}
if (p.get_future().get()) {
std::cout << "Pending buffers played successful !!" << std::endl;
}
6.2 Stop playback operation(FORCE_STOP : Stops immediately, all buffers in pipeline are flushed)
std::promise<bool> p;
auto status = audioPlayStream_->stopAudio(
StopType::FORCE_STOP, [&p](telux::common::ErrorCode error) {
if (error == telux::common::ErrorCode::SUCCESS) {
p.set_value(true);
} else {
p.set_value(false);
std::cout << "Failed to force stop" << std::endl;
}
});
if(status == telux::common::Status::SUCCESS){
std::cout << "Request to force stop Sent" << std::endl;
} else {
std::cout << "Request to force stop failed" << std::endl;
}
if (p.get_future().get()) {
std::cout << "Force Stop successful !!" << std::endl;
}
7. Dispose the audio stream, once end of operation is reached
std::promise<bool> p;
Status status = audioManager-> deleteStream(
audioPlayStream_, [&p,this](ErrorCode error) {
if (error == ErrorCode::SUCCESS) {
p.set_value(true);
} else {
p.set_value(false);
std::cout << "Failed to delete a stream" << std::endl;
}
});
if (status == Status::SUCCESS) {
std::cout << "Request to delete stream sent" << std::endl;
} else {
std::cout << "Request to delete stream failed" << std::endl;
}
if (p.get_future().get()) {
audioPlayStream_= nullptr;
std::cout << "Audio Play Stream is Deleted" << std::endl;
}