blob: a1732aa148b97a7cb7b9afa160a54a65e961d4e8 [file] [log] [blame]
/*
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Changes from Qualcomm Innovation Center are provided under the following license:
*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define LOG_TAG "PAL: SoundTriggerEngine"
#include "SoundTriggerEngine.h"
#include "SoundTriggerEngineGsl.h"
#include "SoundTriggerEngineCapi.h"
#include "Stream.h"
#include "SoundTriggerPlatformInfo.h"
std::shared_ptr<SoundTriggerEngine> SoundTriggerEngine::Create(
Stream *s,
listen_model_indicator_enum type,
st_module_type_t module_type,
std::shared_ptr<VUIStreamConfig> sm_cfg)
{
PAL_VERBOSE(LOG_TAG, "Enter, type %d", type);
if (!s) {
PAL_ERR(LOG_TAG, "Invalid stream handle");
return nullptr;
}
std::shared_ptr<SoundTriggerEngine> st_engine(nullptr);
switch (type) {
case ST_SM_ID_SVA_F_STAGE_GMM:
if (!sm_cfg->GetMergeFirstStageSoundModels() &&
!IS_MODULE_TYPE_PDK(module_type))
st_engine = std::make_shared<SoundTriggerEngineGsl>(s, type,
module_type, sm_cfg);
else
st_engine = SoundTriggerEngineGsl::GetInstance(s, type,
module_type, sm_cfg);
if (!st_engine)
PAL_ERR(LOG_TAG, "SoundTriggerEngine GSL creation failed");
break;
case ST_SM_ID_SVA_S_STAGE_PDK:
case ST_SM_ID_SVA_S_STAGE_RNN:
case ST_SM_ID_SVA_S_STAGE_USER:
case ST_SM_ID_SVA_S_STAGE_UDK:
st_engine = std::make_shared<SoundTriggerEngineCapi>(s, type,
sm_cfg);
if (!st_engine)
PAL_ERR(LOG_TAG, "SoundTriggerEngine capi creation failed");
break;
default:
PAL_ERR(LOG_TAG, "Invalid model type: %u", type);
break;
}
PAL_VERBOSE(LOG_TAG, "Exit, engine %p", st_engine.get());
return st_engine;
}
int32_t SoundTriggerEngine::CreateBuffer(uint32_t buffer_size,
uint32_t engine_size, std::vector<PalRingBufferReader *> &reader_list)
{
int32_t status = 0;
int32_t i = 0;
PalRingBufferReader *reader = nullptr;
if (!buffer_size || !engine_size) {
PAL_ERR(LOG_TAG, "Invalid buffer size or engine number");
status = -EINVAL;
goto exit;
}
if (engine_type_ != ST_SM_ID_SVA_F_STAGE_GMM) {
PAL_ERR(LOG_TAG, "Cannot create buffer in non-GMM engine");
status = -EINVAL;
goto exit;
}
PAL_DBG(LOG_TAG, "Enter");
if (!buffer_) {
buffer_ = new PalRingBuffer(buffer_size);
if (!buffer_) {
PAL_ERR(LOG_TAG, "Failed to allocate memory for ring buffer");
status = -ENOMEM;
goto exit;
}
PAL_VERBOSE(LOG_TAG, "Created a new buffer: %pK with size: %d",
buffer_, buffer_size);
} else {
buffer_->reset();
/* Resize the ringbuffer if it is changed */
if (buffer_->getBufferSize() != buffer_size) {
PAL_VERBOSE(LOG_TAG, "Resize the buffer %pK from old size: %zu to new size: %d",
buffer_, buffer_->getBufferSize(), buffer_size);
buffer_->resizeRingBuffer(buffer_size);
}
/* Reset the readers from existing list*/
for (int32_t i = 0; i < reader_list.size(); i++)
reader_list[i]->reset();
}
if (engine_size != reader_list.size()) {
reader_list.clear();
for (i = 0; i < engine_size; i++) {
reader = buffer_->newReader();
if (!reader) {
PAL_ERR(LOG_TAG, "Failed to create new ring buffer reader");
status = -ENOMEM;
goto exit;
}
reader_list.push_back(reader);
}
}
exit:
PAL_DBG(LOG_TAG, "Exit, status %d", status);
return status;
}
int32_t SoundTriggerEngine::SetBufferReader(PalRingBufferReader *reader)
{
int32_t status = 0;
if (engine_type_ == ST_SM_ID_SVA_F_STAGE_GMM) {
PAL_DBG(LOG_TAG, "No need to set reader for GMM engine");
return status;
}
reader_ = reader;
return status;
}
int32_t SoundTriggerEngine::ResetBufferReaders(
std::vector<PalRingBufferReader *> &reader_list)
{
if (engine_type_ != ST_SM_ID_SVA_F_STAGE_GMM) {
PAL_ERR(LOG_TAG, "Cannot reset buffer readers in non-GMM engine");
return -EINVAL;
}
for (int32_t i = 0; i < reader_list.size(); i++)
buffer_->removeReader(reader_list[i]);
return 0;
}
uint32_t SoundTriggerEngine::UsToBytes(uint64_t input_us) {
uint32_t bytes = 0;
bytes = sample_rate_ * bit_width_ * channels_ * input_us /
(BITS_PER_BYTE * US_PER_SEC);
return bytes;
}
uint32_t SoundTriggerEngine::FrameToBytes(uint32_t frames) {
uint32_t total_bytes, bytes_per_frame = bit_width_ * channels_ / BITS_PER_BYTE;
try {
if ((bytes_per_frame) > (UINT32_MAX / frames))
throw "multiplication overflow due to frames value";
total_bytes = frames * bytes_per_frame;
} catch (const char *e) {
PAL_ERR(LOG_TAG, "FrametoBytes() failed with error %s . frames %u bit_width %u channels: %u",
e, frames, bit_width_, channels_);
return UINT32_MAX;
}
return total_bytes;
}
uint32_t SoundTriggerEngine::BytesToFrames(uint32_t bytes) {
return (bytes * BITS_PER_BYTE) / (bit_width_ * channels_);
}