From: Jaechul Lee Date: Mon, 15 May 2023 05:06:20 +0000 (+0900) Subject: Modify noise suppression functionality X-Git-Tag: accepted/tizen/unified/20230620.022505^0 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fapi%2Faudio-io.git;a=commitdiff_plain;h=63be19f86a48c4c5627685c3a2d29394afbec238 Modify noise suppression functionality This commit added actual NS functionality to audio-io. Furthermore audio_io_process_test was added. [Version] 0.5.56 [Issue Type] New feature Change-Id: Iff85c712541654c764b1fbf7edb279627cdef587 Signed-off-by: Jaechul Lee --- diff --git a/include/CAudioInfo.h b/include/CAudioInfo.h index 4800cad..1b1163b 100644 --- a/include/CAudioInfo.h +++ b/include/CAudioInfo.h @@ -21,6 +21,9 @@ #ifdef __cplusplus #include +#include +#include +#include namespace tizen_media_audio { @@ -139,10 +142,10 @@ namespace tizen_media_audio { int getAudioIndex() noexcept; void setAudioIndex(int audioIndex) noexcept; int getSampleSize() noexcept; - void bindEchoCancelReferenceDeviceId(int id) noexcept; + void bindEchoCancelReferenceDeviceId(int id, sound_acoustic_echo_cancel_type_e type); int getEchoCancelReferenceDeviceId() noexcept; - void setNoiseSuppression(bool enable) noexcept; - bool getNoiseSuppression() noexcept; + void setNoiseSuppression(bool enable, sound_noise_suppression_type_e type); + std::string& getProcessorProperty() noexcept; /* Setter & Getter Utilities */ const char* getConvertedStreamType(); @@ -200,6 +203,7 @@ namespace tizen_media_audio { int __mAudioIndex; int __mReferenceDeviceId; bool __mNoiseSuppression; + std::string __mProcessorProperty; }; diff --git a/packaging/capi-media-audio-io.spec b/packaging/capi-media-audio-io.spec index ba35f46..98554a2 100644 --- a/packaging/capi-media-audio-io.spec +++ b/packaging/capi-media-audio-io.spec @@ -1,6 +1,6 @@ Name: capi-media-audio-io Summary: An Audio Input & Audio Output library in Tizen Native API -Version: 0.5.55 +Version: 0.5.56 Release: 0 Group: Multimedia/API License: Apache-2.0 @@ -91,6 +91,7 @@ find . -name '*.gcno' -exec cp --parents '{}' "$gcno_obj_dir" ';' %files tool %manifest %{name}.manifest %{_prefix}/bin/audio_io_test +%{_prefix}/bin/audio_io_process_test %if 0%{?gcov:1} %files gcov diff --git a/src/cpp/CAudioIO.cpp b/src/cpp/CAudioIO.cpp index 0131b4e..e337973 100644 --- a/src/cpp/CAudioIO.cpp +++ b/src/cpp/CAudioIO.cpp @@ -226,19 +226,20 @@ void CAudioIO::setStreamInfo(sound_stream_info_h stream_info) { if (mDirection == CAudioInfo::EAudioDirection::AUDIO_DIRECTION_IN) { int device_id; - bool enabled; + bool noise_suppression_enabled; + sound_acoustic_echo_cancel_type_e aec_type; + sound_noise_suppression_type_e ns_type; - if ((errorCode = sound_manager_get_echo_cancel_reference_device(stream_info, &device_id)) != SOUND_MANAGER_ERROR_NONE) + if ((errorCode = sound_manager_get_echo_cancel_reference_device(stream_info, &device_id, &aec_type)) != SOUND_MANAGER_ERROR_NONE) THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Can't get reference device [ret:%d]", errorCode); //LCOV_EXCL_LINE if (device_id != SOUND_MANAGER_STREAM_NO_REFERENCE_DEVICE) - getAudioInfo().bindEchoCancelReferenceDeviceId(device_id); + getAudioInfo().bindEchoCancelReferenceDeviceId(device_id, aec_type); - if ((errorCode = sound_manager_get_noise_suppression(stream_info, &enabled)) != SOUND_MANAGER_ERROR_NONE) + if ((errorCode = sound_manager_get_noise_suppression(stream_info, &noise_suppression_enabled, &ns_type)) != SOUND_MANAGER_ERROR_NONE) THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Can't get noise suppression status [ret:%d]", errorCode); //LCOV_EXCL_LINE - if (enabled) - getAudioInfo().setNoiseSuppression(enabled); - + if (noise_suppression_enabled) + getAudioInfo().setNoiseSuppression(noise_suppression_enabled, ns_type); } } diff --git a/src/cpp/CAudioInfo.cpp b/src/cpp/CAudioInfo.cpp index 1fb506b..f5d2666 100644 --- a/src/cpp/CAudioInfo.cpp +++ b/src/cpp/CAudioInfo.cpp @@ -125,7 +125,15 @@ int CAudioInfo::getSampleSize() noexcept { return bytes_in_sample * static_cast(__mChannel); } -void CAudioInfo::bindEchoCancelReferenceDeviceId(int id) noexcept { +void CAudioInfo::bindEchoCancelReferenceDeviceId(int id, sound_acoustic_echo_cancel_type_e type) { + if (type == SOUND_ACOUSTIC_ECHO_CANCEL_VOICE_CALL) + __mProcessorProperty += "webrtc,"; + else if (type == SOUND_ACOUSTIC_ECHO_CANCEL_REFERENCE_COPY) + __mProcessorProperty += "reference_copy,"; + else + THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_NOT_SUPPORTED_TYPE, + "The echo cancel is not supported [type:%d]", type); + __mReferenceDeviceId = id; } @@ -133,12 +141,21 @@ int CAudioInfo::getEchoCancelReferenceDeviceId() noexcept { return __mReferenceDeviceId; } -void CAudioInfo::setNoiseSuppression(bool enable) noexcept { +void CAudioInfo::setNoiseSuppression(bool enable, sound_noise_suppression_type_e type) { + if (type == SOUND_NOISE_SUPPRESSION_VOICE_CALL) { + __mProcessorProperty += "rnnoise,"; + } else if (type == SOUND_NOISE_SUPPRESSION_VOICE_RECOGNITION) { + __mProcessorProperty += "pse,"; + } else { + THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_NOT_SUPPORTED_TYPE, + "The noise suppression type is not supported [type:%d]", type); + } + __mNoiseSuppression = enable; } -bool CAudioInfo::getNoiseSuppression() noexcept { - return __mNoiseSuppression; +std::string& CAudioInfo::getProcessorProperty() noexcept { + return __mProcessorProperty; } const char* CAudioInfo::getConvertedStreamType() { diff --git a/src/cpp/CPulseAudioClient.cpp b/src/cpp/CPulseAudioClient.cpp index 8d4bb43..34f769a 100644 --- a/src/cpp/CPulseAudioClient.cpp +++ b/src/cpp/CPulseAudioClient.cpp @@ -414,12 +414,12 @@ void CPulseAudioClient::initialize() { if (__mDirection == EStreamDirection::STREAM_DIRECTION_RECORD) { int reference_id = __mSpec.getAudioInfo().getEchoCancelReferenceDeviceId(); if (reference_id > 0) { - pa_proplist_setf(__mpPropList, PA_PROP_MEDIA_ECHO_CANCEL_METHOD, "%s", ec_method); pa_proplist_setf(__mpPropList, PA_PROP_MEDIA_ECHO_CANCEL_REFERENCE_DEVICE, "%d", reference_id); } - if (__mSpec.getAudioInfo().getNoiseSuppression()) - pa_proplist_setf(__mpPropList, PA_PROP_MEDIA_NOISE_SUPPRESSION_ENABLE, "%d", true); + if (!__mSpec.getAudioInfo().getProcessorProperty().empty()) + pa_proplist_setf(__mpPropList, PA_PROP_MEDIA_PREPROCESSOR_METHOD, "%s", + __mSpec.getAudioInfo().getProcessorProperty().c_str()); } // Adds latency on proplist for delivery to PULSEAUDIO diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9505dff..9684f82 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -17,3 +17,4 @@ FOREACH(src ${sources}) ENDFOREACH() INSTALL(TARGETS audio_io_test DESTINATION bin) +INSTALL(TARGETS audio_io_process_test DESTINATION bin) diff --git a/test/audio_io_process_test.c b/test/audio_io_process_test.c new file mode 100644 index 0000000..d0e1bfb --- /dev/null +++ b/test/audio_io_process_test.c @@ -0,0 +1,253 @@ +/* +* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include + +static bool arg_aec_is_set; +static int arg_aec_ref; +static sound_acoustic_echo_cancel_type_e arg_aec_type; + +static bool arg_ns_is_set; +static sound_noise_suppression_type_e arg_ns_type; + +static int arg_samplerate; +static audio_channel_e arg_channels; +static audio_sample_type_e arg_format; + +static char arg_filename[256]; + +static int ch_table[] = { 0, AUDIO_CHANNEL_MONO, AUDIO_CHANNEL_STEREO, + AUDIO_CHANNEL_MULTI_3, AUDIO_CHANNEL_MULTI_4, AUDIO_CHANNEL_MULTI_5, + AUDIO_CHANNEL_MULTI_6, AUDIO_CHANNEL_MULTI_7, AUDIO_CHANNEL_MULTI_8, + AUDIO_CHANNEL_MULTI_9, AUDIO_CHANNEL_MULTI_10, AUDIO_CHANNEL_MULTI_11, + AUDIO_CHANNEL_MULTI_12, AUDIO_CHANNEL_MULTI_13, AUDIO_CHANNEL_MULTI_14, + AUDIO_CHANNEL_MULTI_15, AUDIO_CHANNEL_MULTI_16 }; +static void record() +{ + int ret, size; + sound_stream_info_h stream_info; + audio_in_h input = NULL; + FILE *fp = NULL; + char *buffer = NULL; + + sound_device_list_h device_list = NULL; + sound_device_h device; + bool found = false; + int id; + + ret = audio_in_create(arg_samplerate, ch_table[arg_channels], AUDIO_SAMPLE_TYPE_S16_LE, &input); + if (ret != AUDIO_IO_ERROR_NONE) { + printf("audio in create error = 0x%x\n", ret); + goto out; + } + + ret = sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, NULL, NULL, &stream_info); + if (ret) { + printf("fail to sound_manager_create_stream_information(), ret(0x%x)\n", ret); + goto out; + } + + if (arg_aec_is_set) { + if (sound_manager_get_device_list(SOUND_DEVICE_ALL_MASK, &device_list) != SOUND_MANAGER_ERROR_NONE) { + printf("fail to get device list"); + goto out; + } + + while (sound_manager_get_next_device(device_list, &device) == SOUND_MANAGER_ERROR_NONE) { + if (sound_manager_get_device_id(device, &id) != SOUND_MANAGER_ERROR_NONE) + goto out; + + if (arg_aec_ref == id) { + found = true; + break; + } + } + + if (!found) { + printf("Failed to find reference device"); + goto out; + } + + ret = sound_manager_set_echo_cancel_reference_device(stream_info, device, arg_aec_type); + if (ret != SOUND_MANAGER_ERROR_NONE) { + printf("fail to sound_manager_set_echo_cancel_reference_device(), ret(0x%x)\n", ret); + goto out; + } + + /* verify */ + { + int device_id; + int id; + sound_acoustic_echo_cancel_type_e aec_type; + + ret = sound_manager_get_echo_cancel_reference_device(stream_info, &device_id, &aec_type); + if (ret != SOUND_MANAGER_ERROR_NONE) { + printf("fail to sound_manager_get_echo_cancel_reference_device(), ret(0x%x)\n", ret); + goto out; + } + + if (sound_manager_get_device_id(device, &id)) { + printf("fail to sound_manager_device_id\n"); + goto out; + } + + if (device_id != id || arg_aec_type != aec_type) { + printf("fail to verify aec args\n"); + goto out; + } + } + } + + if (arg_ns_is_set) { + ret = sound_manager_set_noise_suppression(stream_info, arg_ns_is_set, arg_ns_type); + if (ret != SOUND_MANAGER_ERROR_NONE) { + printf("failed to sound_manager_set_noise_suppression(), ret(0x%x)\n", ret); + goto out; + } + + /* verify */ + { + bool ns_enabled; + sound_noise_suppression_type_e ns_type; + + ret = sound_manager_get_noise_suppression(stream_info, &ns_enabled, &ns_type); + if (ret != SOUND_MANAGER_ERROR_NONE) { + printf("fail to sound_manager_get_echo_cancel_reference_device(), ret(0x%x)\n", ret); + goto out; + } + + if (arg_ns_is_set != ns_enabled || arg_ns_type != ns_type) { + printf("fail to verify ns args\n"); + goto out; + } + } + } + + ret = audio_in_set_sound_stream_info(input, stream_info); + if (ret != AUDIO_IO_ERROR_NONE) { + printf("fail to audio_in_set_sound_stream_info(), ret(0x%x)\n", ret); + goto out; + } + + ret = audio_in_prepare(input); + if (ret != AUDIO_IO_ERROR_NONE) { + printf("ERROR, prepare\n"); + goto out; + } + + ret = audio_in_get_buffer_size(input, &size); + if (ret != AUDIO_IO_ERROR_NONE) { + printf("ERROR, get_buffer_size\n"); + goto out; + } + + fp = fopen(arg_filename, "wb+"); + if (fp == NULL) { + printf("ERROR, file open failed\n"); + goto out; + } + + buffer = alloca(size); + + while (1) { + ret = audio_in_read(input, (void *)buffer, size); + if (ret <= 0) { + printf("FAIL, size=%d, ret=0x%x\n", size, ret); + goto out; + } + + fwrite(buffer, size, sizeof(char), fp); + } + +out: + if (fp) + fclose(fp); + + if (input) { + audio_in_unprepare(input); + audio_in_destroy(input); + } + + if (device_list) + if (sound_manager_free_device_list(device_list) != SOUND_MANAGER_ERROR_NONE) + printf("fail to free device list\n"); + + return; +} + +int main(int argc, char **argv) +{ + setbuf(stdout, NULL); + const char *optstring = "r:c:f:a:n:o:d:"; + int option; + + arg_channels = AUDIO_CHANNEL_MONO; + arg_format = AUDIO_SAMPLE_TYPE_S16_LE; + + printf("===== Arguments information =====\n"); + while (-1 != (option = getopt(argc, argv, optstring))) { + switch (option) { + case 'r': /* rate */ + arg_samplerate = atoi(optarg); + printf("Samplerate : %d\n", arg_samplerate); + break; + case 'd': /* reference device */ + arg_aec_ref = atoi(optarg); + arg_aec_is_set = true; + printf("AEC reference device : %d\n", arg_aec_ref); + break; + case 'a': /* AEC method */ + arg_aec_type = atoi(optarg); + arg_aec_is_set = true; + printf("AEC reference type: %d\n", arg_aec_type); + break; + case 'n': /* Noise suppression method */ + arg_ns_type = atoi(optarg); + arg_ns_is_set = true; + printf("Noise Suppression Type : %d\n", arg_ns_type); + break; + case 'o': /* output file */ + snprintf(arg_filename, sizeof(arg_filename), "%s", optarg); + printf("Output filename : %s\n", arg_filename); + break; + case 'c': /* channels */ + arg_channels = atoi(optarg); + printf("Channels : %d\n", arg_channels); + break; + case 'f': /* format */ + arg_format = atoi(optarg); + printf("Format : %d\n", arg_format); + break; + case 'h': + default: + printf("audio_io_process_test -r [sample] [-d:reference_device_id] [-a:AEC type] [-n:NS type] -o [output filename]\n"); + printf("audio_io_process_test -r 16000 -d 1 -a 0 -n 0 -o filename\n"); + return 0; + } + } + printf("=================================\n"); + + record(); + printf("END\n"); + + return 0; +} diff --git a/test/audio_io_test.c b/test/audio_io_test.c index b1f81b9..a339872 100644 --- a/test/audio_io_test.c +++ b/test/audio_io_test.c @@ -1,5 +1,5 @@ /* -* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved +* Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -314,7 +314,7 @@ static void *_record_echo_cancel_thread(void *userdata) goto out; } - ret = sound_manager_set_echo_cancel_reference_device(stream_info, device); + ret = sound_manager_set_echo_cancel_reference_device(stream_info, device, SOUND_ACOUSTIC_ECHO_CANCEL_VOICE_CALL); if (ret != SOUND_MANAGER_ERROR_NONE) { printf("fail to sound_manager_set_echo_cancel_reference_device(), ret(0x%x)\n", ret); goto out;