├── .editorconfig ├── .github └── workflows │ ├── c-cpp.yml │ └── eclint.yml ├── .gitignore ├── CMakeLists.txt ├── COPYING ├── README.md ├── cmake └── gtest.cmake ├── evaluation ├── codec_comparison_summery.csv ├── codec_comparison_summery_avx2.csv ├── codec_comparison_summery_other_codecs.csv ├── codec_comparison_summery_sse41.csv ├── decodespeed_vs_compressionrate_16384_classic.png ├── decodespeed_vs_compressionrate_16384_genre.png ├── decodespeed_vs_compressionrate_16384_jazz.png ├── decodespeed_vs_compressionrate_16384_popular.png ├── decodespeed_vs_compressionrate_16384_right.png ├── decodespeed_vs_compressionrate_16384_total.png ├── decodespeed_vs_compressionrate_4096_classic.png ├── decodespeed_vs_compressionrate_4096_genre.png ├── decodespeed_vs_compressionrate_4096_jazz.png ├── decodespeed_vs_compressionrate_4096_popular.png ├── decodespeed_vs_compressionrate_4096_right.png ├── decodespeed_vs_compressionrate_4096_total.png ├── decodespeed_vs_compressionrate_8192_classic.png ├── decodespeed_vs_compressionrate_8192_genre.png ├── decodespeed_vs_compressionrate_8192_jazz.png ├── decodespeed_vs_compressionrate_8192_popular.png ├── decodespeed_vs_compressionrate_8192_right.png ├── decodespeed_vs_compressionrate_8192_total.png ├── encodespeed_vs_compressionrate_16384_classic.png ├── encodespeed_vs_compressionrate_16384_genre.png ├── encodespeed_vs_compressionrate_16384_jazz.png ├── encodespeed_vs_compressionrate_16384_popular.png ├── encodespeed_vs_compressionrate_16384_right.png ├── encodespeed_vs_compressionrate_16384_total.png ├── encodespeed_vs_compressionrate_4096_classic.png ├── encodespeed_vs_compressionrate_4096_genre.png ├── encodespeed_vs_compressionrate_4096_jazz.png ├── encodespeed_vs_compressionrate_4096_popular.png ├── encodespeed_vs_compressionrate_4096_right.png ├── encodespeed_vs_compressionrate_4096_total.png ├── encodespeed_vs_compressionrate_8192_classic.png ├── encodespeed_vs_compressionrate_8192_genre.png ├── encodespeed_vs_compressionrate_8192_jazz.png ├── encodespeed_vs_compressionrate_8192_popular.png ├── encodespeed_vs_compressionrate_8192_right.png ├── encodespeed_vs_compressionrate_8192_total.png ├── evaluate_codecs.py └── plot_codec_performance_graph.py ├── include ├── srla.h ├── srla_decoder.h ├── srla_encoder.h └── srla_stdint.h ├── libs ├── CMakeLists.txt ├── bit_stream │ ├── CMakeLists.txt │ ├── include │ │ └── bit_stream.h │ └── src │ │ ├── CMakeLists.txt │ │ └── bit_stream.c ├── byte_array │ ├── CMakeLists.txt │ └── include │ │ └── byte_array.h ├── command_line_parser │ ├── CMakeLists.txt │ ├── include │ │ └── command_line_parser.h │ └── src │ │ ├── CMakeLists.txt │ │ └── command_line_parser.c ├── fft │ ├── CMakeLists.txt │ ├── include │ │ └── fft.h │ └── src │ │ ├── CMakeLists.txt │ │ └── fft.c ├── lpc │ ├── CMakeLists.txt │ ├── include │ │ └── lpc.h │ └── src │ │ ├── CMakeLists.txt │ │ └── lpc.c ├── srla_coder │ ├── CMakeLists.txt │ ├── include │ │ └── srla_coder.h │ └── src │ │ ├── CMakeLists.txt │ │ └── srla_coder.c ├── srla_decoder │ ├── CMakeLists.txt │ └── src │ │ ├── CMakeLists.txt │ │ ├── srla_decoder.c │ │ ├── srla_lpc_synthesize.c │ │ └── srla_lpc_synthesize.h ├── srla_encoder │ ├── CMakeLists.txt │ └── src │ │ ├── CMakeLists.txt │ │ ├── srla_encoder.c │ │ ├── srla_lpc_predict.c │ │ └── srla_lpc_predict.h ├── srla_internal │ ├── CMakeLists.txt │ ├── include │ │ ├── srla_internal.h │ │ └── srla_utility.h │ └── src │ │ ├── CMakeLists.txt │ │ ├── srla_internal.c │ │ └── srla_utility.c ├── static_huffman │ ├── CMakeLists.txt │ ├── include │ │ └── static_huffman.h │ └── src │ │ ├── CMakeLists.txt │ │ └── static_huffman.c └── wav │ ├── CMakeLists.txt │ ├── include │ └── wav.h │ └── src │ ├── CMakeLists.txt │ └── wav.c ├── test ├── CMakeLists.txt ├── bit_stream │ ├── CMakeLists.txt │ ├── bit_stream_common_test.cpp │ ├── bit_stream_function_test.cpp │ ├── bit_stream_macro_test.cpp │ └── main.cpp ├── byte_array │ ├── CMakeLists.txt │ └── main.cpp ├── command_line_parser │ ├── CMakeLists.txt │ └── main.cpp ├── fft │ ├── CMakeLists.txt │ └── main.cpp ├── lpc │ ├── CMakeLists.txt │ └── main.cpp ├── srla_coder │ ├── CMakeLists.txt │ ├── PriChanIcon.png │ └── main.cpp ├── srla_decoder │ ├── CMakeLists.txt │ ├── main.cpp │ ├── srla_decoder_test.cpp │ └── srla_lpc_synthesize_test.cpp ├── srla_encode_decode │ ├── CMakeLists.txt │ └── main.cpp ├── srla_encoder │ ├── CMakeLists.txt │ ├── main.cpp │ ├── srla_encoder_test.cpp │ └── srla_lpc_predict_test.cpp ├── srla_internal │ ├── CMakeLists.txt │ ├── PriChanIcon.png │ ├── a.wav │ └── main.cpp ├── static_huffman │ ├── CMakeLists.txt │ ├── main.cpp │ └── test.txt └── wav │ ├── 16bit.wav │ ├── 16bit_2ch.wav │ ├── 24bit.wav │ ├── 24bit_2ch.wav │ ├── 32bit.wav │ ├── 32bit_2ch.wav │ ├── 8bit.wav │ ├── 8bit_2ch.wav │ ├── CMakeLists.txt │ ├── a.wav │ └── main.cpp └── tools ├── srla_codec ├── CMakeLists.txt └── srla_codec.c └── srla_player ├── CMakeLists.txt ├── srla_player.c ├── srla_player.h ├── srla_player_coreaudio.c ├── srla_player_pulseaudio.c └── srla_player_wasapi.c /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.yml] 12 | indent_size = 2 13 | trim_trailing_whitespace = false 14 | 15 | [*.rb] 16 | indent_size = 2 17 | -------------------------------------------------------------------------------- /.github/workflows/c-cpp.yml: -------------------------------------------------------------------------------- 1 | name: C/C++ CI 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | push: 7 | branches: [ main ] 8 | pull_request: 9 | branches: [ main ] 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ${{ matrix.os }} 16 | strategy: 17 | matrix: 18 | os: [ubuntu-20.04, ubuntu-latest, macos-latest, windows-latest] 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | - name: Preparation on Linux 24 | if: runner.os == 'Linux' 25 | run: | 26 | sudo apt-get update 27 | sudo apt-get install libpulse-dev 28 | 29 | - name: Preparation on Windows 30 | if: runner.os == 'Windows' 31 | uses: microsoft/setup-msbuild@v2 32 | 33 | - name: Build libraries 34 | run: | 35 | cmake -B build_debug -DCMAKE_BUILD_TYPE=Debug 36 | cmake --build build_debug --config Debug 37 | cmake -B build_release -DCMAKE_BUILD_TYPE=Release 38 | cmake --build build_release --config Release 39 | 40 | - name: Test 41 | run: | 42 | pushd build_debug 43 | ctest -C Debug 44 | popd 45 | pushd build_release 46 | ctest -C Release 47 | popd 48 | 49 | - name: Build tools 50 | run: | 51 | pushd tools/srla_codec 52 | cmake -B build -DCMAKE_BUILD_TYPE=Release 53 | cmake --build build --config Release 54 | popd 55 | pushd tools/srla_player 56 | cmake -B build -DCMAKE_BUILD_TYPE=Release 57 | cmake --build build --config Release 58 | popd 59 | 60 | - name: Build SSE/AVX libraries and tools 61 | if: runner.os == 'Windows' || runner.os == 'Linux' 62 | run: | 63 | cmake -B build_release_sse41 -DCMAKE_BUILD_TYPE=Release -DUSE_SIMD_INTRINSICS=SSE41 64 | cmake --build build_release_sse41 --config Release 65 | cmake -B build_release_avx2 -DCMAKE_BUILD_TYPE=Release -DUSE_SIMD_INTRINSICS=AVX2 66 | cmake --build build_release_avx2 --config Release 67 | pushd build_release_sse41 68 | ctest -C Release 69 | popd 70 | pushd build_release_avx2 71 | ctest -C Release 72 | popd 73 | pushd tools/srla_codec 74 | cmake -B build_sse41 -DCMAKE_BUILD_TYPE=Release -DUSE_SIMD_INTRINSICS=SSE41 75 | cmake --build build_sse41 --config Release 76 | popd 77 | pushd tools/srla_player 78 | cmake -B build_sse41 -DCMAKE_BUILD_TYPE=Release -DUSE_SIMD_INTRINSICS=SSE41 79 | cmake --build build_sse41 --config Release 80 | popd 81 | pushd tools/srla_codec 82 | cmake -B build_avx2 -DCMAKE_BUILD_TYPE=Release -DUSE_SIMD_INTRINSICS=AVX2 83 | cmake --build build_avx2 --config Release 84 | popd 85 | pushd tools/srla_player 86 | cmake -B build_avx2 -DCMAKE_BUILD_TYPE=Release -DUSE_SIMD_INTRINSICS=AVX2 87 | cmake --build build_avx2 --config Release 88 | popd 89 | 90 | - name: Create artifacts on Linux platform 91 | if: runner.os == 'Linux' 92 | run: | 93 | ARTIFACT_ROOT=srla_${{ matrix.os }} 94 | mkdir ${ARTIFACT_ROOT} 95 | pushd ${ARTIFACT_ROOT} 96 | mkdir include && mkdir libs && mkdir tools 97 | popd 98 | cp include/*.h ${ARTIFACT_ROOT}/include/ 99 | cp build_release/libsrlacodec.a ${ARTIFACT_ROOT}/libs/ 100 | cp build_release/libsrladec.a ${ARTIFACT_ROOT}/libs/ 101 | cp tools/srla_codec/build/srla ${ARTIFACT_ROOT}/tools/ 102 | cp tools/srla_player/build/srlaplayer ${ARTIFACT_ROOT}/tools/ 103 | tar -czf ${ARTIFACT_ROOT}.tar.gz ${ARTIFACT_ROOT} 104 | ARTIFACT_ROOT_SSE41=srla_${{ matrix.os }}_sse41 105 | mkdir ${ARTIFACT_ROOT_SSE41} 106 | pushd ${ARTIFACT_ROOT_SSE41} 107 | mkdir include && mkdir libs && mkdir tools 108 | popd 109 | cp include/*.h ${ARTIFACT_ROOT_SSE41}/include/ 110 | cp build_release_sse41/libsrlacodec.a ${ARTIFACT_ROOT_SSE41}/libs/ 111 | cp build_release_sse41/libsrladec.a ${ARTIFACT_ROOT_SSE41}/libs/ 112 | cp tools/srla_codec/build_sse41/srla ${ARTIFACT_ROOT_SSE41}/tools/ 113 | cp tools/srla_player/build_sse41/srlaplayer ${ARTIFACT_ROOT_SSE41}/tools/ 114 | tar -czf ${ARTIFACT_ROOT_SSE41}.tar.gz ${ARTIFACT_ROOT_SSE41} 115 | ARTIFACT_ROOT_AVX2=srla_${{ matrix.os }}_avx2 116 | mkdir ${ARTIFACT_ROOT_AVX2} 117 | pushd ${ARTIFACT_ROOT_AVX2} 118 | mkdir include && mkdir libs && mkdir tools 119 | popd 120 | cp include/*.h ${ARTIFACT_ROOT_AVX2}/include/ 121 | cp build_release_avx2/libsrlacodec.a ${ARTIFACT_ROOT_AVX2}/libs/ 122 | cp build_release_avx2/libsrladec.a ${ARTIFACT_ROOT_AVX2}/libs/ 123 | cp tools/srla_codec/build_avx2/srla ${ARTIFACT_ROOT_AVX2}/tools/ 124 | cp tools/srla_player/build_avx2/srlaplayer ${ARTIFACT_ROOT_AVX2}/tools/ 125 | tar -czf ${ARTIFACT_ROOT_AVX2}.tar.gz ${ARTIFACT_ROOT_AVX2} 126 | 127 | - name: Create artifacts on macOS platform 128 | if: runner.os == 'macOS' 129 | run: | 130 | ARTIFACT_ROOT=srla_${{ matrix.os }} 131 | mkdir ${ARTIFACT_ROOT} 132 | pushd ${ARTIFACT_ROOT} 133 | mkdir include && mkdir libs && mkdir tools 134 | popd 135 | cp include/*.h ${ARTIFACT_ROOT}/include/ 136 | cp build_release/libsrlacodec.a ${ARTIFACT_ROOT}/libs/ 137 | cp build_release/libsrladec.a ${ARTIFACT_ROOT}/libs/ 138 | cp tools/srla_codec/build/srla ${ARTIFACT_ROOT}/tools/ 139 | cp tools/srla_player/build/srlaplayer ${ARTIFACT_ROOT}/tools/ 140 | tar -czf ${ARTIFACT_ROOT}.tar.gz ${ARTIFACT_ROOT} 141 | 142 | - name: Create artifacts on Windows platform 143 | if: runner.os == 'Windows' 144 | shell: powershell 145 | run: | 146 | $ARTIFACT_ROOT = "srla_${{ matrix.os }}" 147 | mkdir ${ARTIFACT_ROOT} 148 | pushd ${ARTIFACT_ROOT} 149 | mkdir include 150 | mkdir libs 151 | mkdir tools 152 | popd 153 | cp include/*.h ${ARTIFACT_ROOT}/include/ 154 | cp build_release/Release/srlacodec.lib ${ARTIFACT_ROOT}/libs/ 155 | cp build_release/Release/srladec.lib ${ARTIFACT_ROOT}/libs/ 156 | cp tools/srla_codec/build/Release/srla.exe ${ARTIFACT_ROOT}/tools/ 157 | cp tools/srla_player/build/Release/srlaplayer.exe ${ARTIFACT_ROOT}/tools/ 158 | tar -czf "${ARTIFACT_ROOT}.tar.gz" ${ARTIFACT_ROOT} 159 | $ARTIFACT_ROOT_SSE41 = "srla_${{ matrix.os }}_sse41" 160 | mkdir ${ARTIFACT_ROOT_SSE41} 161 | pushd ${ARTIFACT_ROOT_SSE41} 162 | mkdir include 163 | mkdir libs 164 | mkdir tools 165 | popd 166 | cp include/*.h ${ARTIFACT_ROOT_SSE41}/include/ 167 | cp build_release_sse41/Release/srlacodec.lib ${ARTIFACT_ROOT_SSE41}/libs/ 168 | cp build_release_sse41/Release/srladec.lib ${ARTIFACT_ROOT_SSE41}/libs/ 169 | cp tools/srla_codec/build_sse41/Release/srla.exe ${ARTIFACT_ROOT_SSE41}/tools/ 170 | cp tools/srla_player/build_sse41/Release/srlaplayer.exe ${ARTIFACT_ROOT_SSE41}/tools/ 171 | tar -czf "${ARTIFACT_ROOT_SSE41}.tar.gz" ${ARTIFACT_ROOT_SSE41} 172 | $ARTIFACT_ROOT_AVX2 = "srla_${{ matrix.os }}_avx2" 173 | mkdir ${ARTIFACT_ROOT_AVX2} 174 | pushd ${ARTIFACT_ROOT_AVX2} 175 | mkdir include 176 | mkdir libs 177 | mkdir tools 178 | popd 179 | cp include/*.h ${ARTIFACT_ROOT_AVX2}/include/ 180 | cp build_release_avx2/Release/srlacodec.lib ${ARTIFACT_ROOT_AVX2}/libs/ 181 | cp build_release_avx2/Release/srladec.lib ${ARTIFACT_ROOT_AVX2}/libs/ 182 | cp tools/srla_codec/build_avx2/Release/srla.exe ${ARTIFACT_ROOT_AVX2}/tools/ 183 | cp tools/srla_player/build_avx2/Release/srlaplayer.exe ${ARTIFACT_ROOT_AVX2}/tools/ 184 | tar -czf "${ARTIFACT_ROOT_AVX2}.tar.gz" ${ARTIFACT_ROOT_AVX2} 185 | 186 | - name: Upload artifacts on macOS platform 187 | if: runner.os == 'macOS' 188 | uses: actions/upload-artifact@v4 189 | with: 190 | name: artifacts_${{ matrix.os }} 191 | path: | 192 | srla_${{ matrix.os }}.tar.gz 193 | 194 | - name: Upload artifacts on Linux / Windows platforms 195 | if: runner.os == 'Linux' || runner.os == 'Windows' 196 | uses: actions/upload-artifact@v4 197 | with: 198 | name: artifacts_${{ matrix.os }} 199 | path: | 200 | srla_${{ matrix.os }}.tar.gz 201 | srla_${{ matrix.os }}_sse41.tar.gz 202 | srla_${{ matrix.os }}_avx2.tar.gz 203 | -------------------------------------------------------------------------------- /.github/workflows/eclint.yml: -------------------------------------------------------------------------------- 1 | name: eclint 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v3 16 | - name: ECLint 17 | uses: snow-actions/eclint@v1.0.1 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | tmp 3 | data 4 | *.o 5 | *.swp 6 | *.swo 7 | *~ 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | # コーデックライブラリ 4 | project(SRLACodecLibrary C) 5 | set(CODEC_LIB_NAME srlacodec) 6 | add_library(${CODEC_LIB_NAME} 7 | STATIC 8 | $ 9 | $ 10 | $ 11 | $ 12 | $ 13 | $ 14 | $ 15 | $ 16 | ) 17 | 18 | # デコーダライブラリ 19 | project(SRLADecoderLibrary C) 20 | set(DECODER_LIB_NAME srladec) 21 | add_library(${DECODER_LIB_NAME} 22 | STATIC 23 | $ 24 | $ 25 | $ 26 | $ 27 | $ 28 | ) 29 | 30 | # SIMD命令をどこまで使うか? 31 | set(USE_SIMD_INTRINSICS "" CACHE STRING "Using SIMD operations (SSE41 or AVX2)") 32 | if("${USE_SIMD_INTRINSICS}" STREQUAL "SSE41") 33 | add_compile_definitions(SRLA_USE_SSE41) 34 | if(NOT MSVC) 35 | add_compile_options(-msse4.1) 36 | endif() 37 | elseif("${USE_SIMD_INTRINSICS}" STREQUAL "AVX2") 38 | add_compile_definitions(SRLA_USE_AVX2) 39 | if(MSVC) 40 | add_compile_options(/arch:AVX2) 41 | else() 42 | add_compile_options(-msse4.1 -mavx2) 43 | endif() 44 | endif() 45 | 46 | # 最適化オプション 47 | if(MSVC) 48 | set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Oi /Ot /Oy /GL") 49 | set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG") 50 | endif() 51 | 52 | # 依存するプロジェクト 53 | add_subdirectory(libs) 54 | 55 | # テスト 56 | if(NOT without-test) 57 | enable_testing() 58 | # C++環境でないとgtestがビルドできないので、CXXプロジェクトを作る 59 | # -> Cとの挙動で差異が生じるかもしれない... 60 | project(SRLATest CXX) 61 | if(MSVC) 62 | set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 63 | else() 64 | set(CMAKE_CXX_FLAGS "-std=gnu++11") # gtestがGNU独自拡張を使用しているため 65 | set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3 -DDEBUG") 66 | set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") 67 | endif() 68 | include(cmake/gtest.cmake) 69 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) 70 | add_subdirectory(test) 71 | endif() 72 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 aikiriao 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![eclint](https://github.com/aikiriao/SRLA/workflows/eclint/badge.svg?branch=main) 2 | ![C/C++ CI](https://github.com/aikiriao/SRLA/workflows/C/C++%20CI/badge.svg?branch=main) 3 | ![Repo size](https://img.shields.io/github/repo-size/aikiriao/SRLA) 4 | ![License](https://img.shields.io/github/license/aikiriao/SRLA) 5 | 6 | # SRLA 7 | 8 | aka Soleil Rising Lossless Audio codec 9 | 10 | # How to build 11 | 12 | ## Requirement 13 | 14 | * [CMake](https://cmake.org) >= 3.15 15 | 16 | ## Build SRLA Codec 17 | 18 | ```bash 19 | git clone https://github.com/aikiriao/SRLA.git 20 | cd SRLA/tools/srla_codec 21 | cmake -B build 22 | cmake --build build 23 | ``` 24 | 25 | # Usage 26 | 27 | ## SRLA Codec 28 | 29 | ### Encode 30 | 31 | ```bash 32 | ./srla -e INPUT.wav OUTPUT.srl 33 | ``` 34 | 35 | #### Mode `-m` 36 | 37 | You can change compression mode by `-m` option. 38 | Following example encoding in maximum compression (but slow) option. 39 | 40 | ```bash 41 | ./srla -e -m 4 INPUT.wav OUTPUT.srl 42 | ``` 43 | #### Max block size `-B` 44 | 45 | You can change maximum block size by `-B` option. 46 | Following example encoding with maximum block size be 4096 sample. 47 | 48 | ```bash 49 | ./srla -e -B 4096 INPUT.wav OUTPUT.srl 50 | ``` 51 | 52 | #### Number of divisions in block `-V` 53 | 54 | You can change number of division by `-V` option. Number of division specifies search depth of optimal block division. 55 | Following example encoding with number of divisions in block to be $2^{2} = 4$. 56 | 57 | ```bash 58 | ./srla -e -V 2 INPUT.wav OUTPUT.srl 59 | ``` 60 | 61 | ### Decode 62 | 63 | ```bash 64 | ./srla -d INPUT.srl OUTPUT.wav 65 | ``` 66 | ## Performance 67 | 68 | We use [RWC music dataset](https://staff.aist.go.jp/m.goto/RWC-MDB/) for comparison. 69 | 70 | ### Decoding speed vs compression ratio 71 | 72 | ![Decoding speed vs compression rate](./evaluation/decodespeed_vs_compressionrate_8192_total.png) 73 | 74 | ### Encoding speed vs compression ratio 75 | 76 | ![Encoding speed vs compression rate](./evaluation/encodespeed_vs_compressionrate_8192_total.png) 77 | 78 | ## License 79 | 80 | MIT 81 | -------------------------------------------------------------------------------- /cmake/gtest.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | # Google Test settings 4 | include(ExternalProject) 5 | 6 | # gtest追加 7 | ExternalProject_Add(GoogleTest 8 | GIT_REPOSITORY https://github.com/google/googletest.git 9 | GIT_TAG release-1.12.0 10 | INSTALL_COMMAND "" 11 | LOG_DOWNLOAD ON 12 | ) 13 | 14 | # インクルードパス追加 15 | ExternalProject_Get_Property(GoogleTest source_dir) 16 | include_directories(${source_dir}/googletest/include) 17 | 18 | # 成果物のディレクトリ取得 19 | ExternalProject_Get_Property(GoogleTest binary_dir) 20 | 21 | # ライブラリ追加 22 | add_library(gtest STATIC IMPORTED) 23 | if(MSVC) 24 | set_target_properties(gtest 25 | PROPERTIES 26 | IMPORTED_LOCATION "${binary_dir}/lib/Debug/gtest.lib" 27 | IMPORTED_LOCATION_DEBUG "${binary_dir}/lib/Debug/gtest.lib" 28 | IMPORTED_LOCATION_RELEASE "${binary_dir}/lib/Release/gtest.lib" 29 | ) 30 | else() 31 | set_target_properties(gtest 32 | PROPERTIES 33 | IMPORTED_LOCATION ${binary_dir}/lib/libgtest.a 34 | ) 35 | endif() 36 | 37 | # メインエントリ追加 38 | add_library(gtest_main STATIC IMPORTED) 39 | if(MSVC) 40 | set_target_properties(gtest_main 41 | PROPERTIES 42 | IMPORTED_LOCATION "${binary_dir}/lib/Debug/gtest_main.lib" 43 | IMPORTED_LOCATION_DEBUG "${binary_dir}/lib/Debug/gtest_main.lib" 44 | IMPORTED_LOCATION_RELEASE "${binary_dir}/lib/Release/gtest_main.lib" 45 | ) 46 | else() 47 | set_target_properties(gtest_main 48 | PROPERTIES 49 | IMPORTED_LOCATION ${binary_dir}/lib/libgtest_main.a 50 | ) 51 | endif() 52 | -------------------------------------------------------------------------------- /evaluation/codec_comparison_summery_other_codecs.csv: -------------------------------------------------------------------------------- 1 | ,FLAC -0,FLAC -5,FLAC -8,WavPack ,WavPack -h,WavPack -hh,WavPack -x4,WavPack -h -x4,WavPack -hh -x4,TTA,Monkey's Audio -c1000,Monkey's Audio -c2000,Monkey's Audio -c3000,Monkey's Audio -c4000,MPEG4-ALS ,MPEG4-ALS -b,MPEG4-ALS -7,TAK -p0,TAK -p0e,TAK -p0m,TAK -p1,TAK -p1e,TAK -p1m,TAK -p2,TAK -p2e,TAK -p2m,TAK -p3,TAK -p3e,TAK -p3m,TAK -p4,TAK -p4e,TAK -p4m 2 | classic mean encode time,0.0598823312736089,0.0815155808584222,0.181855618987059,0.188867913703307,0.288039207804022,0.385712286208112,4.11519191265898,6.01111900246445,8.2500226925692,0.135434077034623,0.164488449044607,0.231636320723362,0.244538382673765,0.34522989122258,0.6423414647629,0.90346359370211,29.3558973099318,0.0636050747401706,0.0773790007086232,0.119168266760076,0.0736782039747558,0.104427661339849,0.148813541311766,0.0881765712102644,0.136967551047145,0.226862313948918,0.154837796292913,0.187924384809088,0.330809652138854,0.243908128715495,0.284390431773816,0.503067834931663 3 | genre mean encode time,0.061329245258767,0.0825229112801024,0.190398725677265,0.194071015605659,0.29444009732261,0.391380402755802,3.67969735509601,5.63727775466112,8.51967645951332,0.138163184487929,0.167973736577267,0.237412991284732,0.252022373442433,0.350232465125713,0.644801871693494,0.932792544262666,26.4979842198452,0.0690070403126443,0.0830278352900525,0.125573956865127,0.0798287062890239,0.114572633156068,0.157874082048387,0.0949587000054461,0.146973810605156,0.238923241882946,0.164745226503809,0.198417612516552,0.35765672399439,0.26078370494691,0.30422337283892,0.593754555307517 4 | jazz mean encode time,0.0593045536737118,0.0808831914880769,0.190368487738308,0.190297349788364,0.289705407493905,0.385987653501416,3.93367161282057,5.91277253180515,8.89538770240618,0.135878405422795,0.164315345408446,0.231430563320697,0.245666637537538,0.342301219478631,0.645068529509943,0.915350642545995,28.065956186899,0.064591753396208,0.0782496232984835,0.120487087134164,0.0750471649887942,0.106884238014506,0.152382676308277,0.089714208157497,0.14048352493115,0.232010104059821,0.158279800273749,0.192021897707821,0.344290924896407,0.253254169590938,0.295229459588252,0.559404636035691 5 | popular mean encode time,0.0619754099252875,0.0828739079027314,0.192175939915009,0.196105765204945,0.296468642052967,0.393003164421869,3.65912882175897,5.60725460073493,8.46971221062923,0.1411283675146,0.172210528454432,0.24678067700344,0.25731522448589,0.357084194481054,0.644992491419439,0.937817645969876,26.4558463681039,0.0719723725077779,0.0861062271118967,0.12910148232501,0.0830817511062685,0.115790442003158,0.161270575797078,0.0986066691848587,0.151012304423025,0.243633242425338,0.169277093163039,0.203242049632486,0.363133539093438,0.265733306874715,0.309400444762926,0.599315861264768 6 | right mean encode time,0.0682718384692684,0.0886727261065046,0.195927304958584,0.198520470622802,0.299479791875731,0.395190550197557,3.74613825345965,5.68428043729926,8.49234643612028,0.139009335672624,0.171915193943034,0.239584993739598,0.256903105256379,0.357016797403023,0.646124026678702,0.933200319086504,28.0372225848788,0.0751810660698319,0.0893580199753153,0.131003843501013,0.0855949655627573,0.11739782276258,0.161767362164691,0.100479279312787,0.152101870621062,0.240915097575598,0.168841874045241,0.202082446305057,0.350963786298577,0.261129616399738,0.303916404582153,0.551880771677961 7 | total mean encode time,0.0613058508609788,0.0825156874995616,0.189947033146557,0.193271854677065,0.293260275265607,0.38995222992601,3.80853979673228,5.75703557300619,8.54815831633354,0.138141551193182,0.168110500587094,0.238060307519481,0.251262709758125,0.350107469238703,0.644620407439564,0.925486590360896,27.4267017382324,0.0684286539219355,0.0823690621693412,0.124792312215131,0.0791011926099388,0.111686229419015,0.156419798302464,0.094122025814256,0.145412945182926,0.236911817376736,0.163282502525794,0.196935058013031,0.351348817373132,0.257806059617551,0.300444758718247,0.569711770333348 8 | classic mean decode time,0.0683828963775558,0.0696738717896994,0.0705975164030152,0.166151930679265,0.21551186847471,0.261952182165393,0.1615316141051,0.199783784955183,0.232252100409603,0.166937312100894,0.190856972063109,0.245518658423207,0.255456369866636,0.354435863705644,0.223012937010123,0.407347330900081,2.08106096457201,0.0858400698115394,0.0871777204408366,0.0876123525401227,0.0928909482700956,0.0915428038529072,0.0924944020892562,0.0959507789795314,0.097149664775606,0.0981278043216749,0.0983320892395104,0.0981420889679974,0.0994130650842111,0.103471671790614,0.104127207534794,0.103382239173963 9 | genre mean decode time,0.0687366245514067,0.0722151702434879,0.0735021364125756,0.168922282749082,0.217038127039919,0.262201375408478,0.164497205284006,0.207904204465891,0.254229199493706,0.16622899869739,0.195747552125563,0.256563211743762,0.266203667240432,0.367330740948916,0.223827407336461,0.43339151289538,0.955147722406259,0.093643341886229,0.0922977296192037,0.0957120192699089,0.097613980041422,0.0981407852643669,0.0986487043689071,0.101036297761985,0.102930110061349,0.103964934921235,0.103747621381736,0.104523979174204,0.105136853328845,0.107352373545758,0.10699192710541,0.106763507945036 10 | jazz mean decode time,0.0673495983083599,0.0697398224226875,0.0719121867819785,0.166432893817414,0.214918379165258,0.259734965088948,0.162142850566519,0.205447833264762,0.252032882230723,0.166673033887824,0.191395173911936,0.249448319925675,0.258823741697011,0.353799227722518,0.224022356620051,0.416407210938924,1.40265367709552,0.0879723322274058,0.0890115761341596,0.0889075215622801,0.0922169344834765,0.0938734463136905,0.0940849029467851,0.0967857838496637,0.0979779009867714,0.0985869790471553,0.098794184654512,0.0994789955079989,0.100375878662482,0.103668338466626,0.103323547672022,0.102995938372965 11 | popular mean decode time,0.0689583388310129,0.0727317177059943,0.0741403732440939,0.169864048336264,0.217583266553885,0.261499298026724,0.165488793482197,0.206157105176097,0.253361132080468,0.168869217465874,0.201743919574618,0.263244815355908,0.273463618997557,0.374299593881848,0.226306090725634,0.437162849500517,0.919958776318019,0.096572506180668,0.0966824840841474,0.0971373593008597,0.10198114981443,0.101624279371685,0.101985261119154,0.10571883514374,0.108437229346787,0.107907156194062,0.108290453120006,0.108747355818342,0.109286305524102,0.111412555881446,0.111544277124172,0.111001826837308 12 | right mean decode time,0.0757608403310264,0.0790287302450102,0.0796821789239124,0.174504174979741,0.219823468220665,0.265011896294299,0.168352160066264,0.209741445944732,0.252038532246646,0.167464964873675,0.198852191414978,0.260042126699503,0.268867600363015,0.378326464405856,0.227309514352129,0.435062220667324,1.50318739624776,0.0988763899826624,0.0988148866678802,0.100086070158558,0.102172779940485,0.102528187410465,0.103756006724338,0.109440445444983,0.107916716340388,0.110051318697405,0.11506587326152,0.10985149911254,0.111301950142183,0.114198342931035,0.114265021016126,0.113575627212522 13 | total mean decode time,0.0689175481557945,0.0718601508082008,0.0732902560004065,0.168568443716297,0.216653240128331,0.261563611307121,0.164036248556333,0.205614306097243,0.249748376957394,0.167337045659798,0.195967639676634,0.255371491135754,0.265114527531497,0.364941835508018,0.224741733474973,0.426432787178058,1.27090530783789,0.0923025859753758,0.0924872730086343,0.0935377015974748,0.0972227265145789,0.0974348911389468,0.0979506608557934,0.101227346451359,0.102850058568503,0.10337838366064,0.103883711809457,0.103959881799695,0.104783222329133,0.107572257889984,0.107558881478828,0.107095700273461 14 | classic mean compression rate,46.8530936782795,44.0811021191108,43.9772749664826,44.2881854553595,43.9733190246296,43.9059643141556,43.8416002132112,43.6312762966246,43.6059908393894,43.9649583934312,43.7471845512139,43.1347465735196,42.3583904931674,41.2750202242955,43.6722765576111,43.0469250255674,40.096338802651,43.9250297153855,43.7976877716099,43.6984004139462,43.3952408436558,43.3161949017682,43.2375914163449,43.0248262448756,42.9512588845291,42.8624500016805,42.055640115921,42.0074820799585,41.9411529879097,41.3103192868066,41.2826658041786,41.2113934618781 15 | genre mean compression rate,63.7165252359267,58.7313476626937,58.3572227198886,58.560758314416,57.9115764694669,57.6353869906248,58.0865954425887,57.6004310881945,57.4595687600063,58.1957450750065,58.1943555312307,57.0904331175579,56.7407590485577,56.205207076518,58.167016644217,57.600464114111,56.5545540507662,58.5188112193204,58.0868753040305,57.9899950590224,57.6153069399109,57.3427117727007,57.2509872218427,57.1921192603756,57.0398884721665,56.937929416272,56.771169671284,56.7120985063178,56.6572484372621,56.5486783220347,56.4916466530135,56.4576127304698 16 | jazz mean compression rate,52.0153590903936,48.0107793597457,47.698761291478,48.2032470310796,47.6592605514502,47.4326638973771,47.6957660409606,47.2529258100839,47.1483283990533,47.6383199967399,47.7454608533694,46.5752268157761,46.1969723307326,45.5126722561316,47.5110601912575,46.9131436101885,45.4862631614839,48.0013634477051,47.6958851351536,47.5835478603572,47.0260179870651,46.851737479841,46.7512330314008,46.6938423879729,46.5584926268621,46.4427984317702,46.1860298992831,46.1270987182688,46.0692228345583,45.8052385293301,45.7532227792948,45.7061978627442 17 | popular mean compression rate,74.3401641316921,68.2604877715884,67.8795466972007,68.1155043904673,67.4673290867506,67.1849687943123,67.6718530221254,67.1837336981033,67.0464889110846,67.7246487241366,67.6336530518968,66.6398706483345,66.2224987752685,65.7096182682847,67.7021639646981,67.1711978380265,66.0804786672614,67.963407270921,67.5651860785683,67.4636802849799,67.209285642185,66.930041699861,66.8337412644384,66.7129654786514,66.5367569921028,66.4410997072067,66.2717617895269,66.2184868151787,66.1618331881241,66.063229499044,66.0080940511255,65.9736188776493 18 | right mean compression rate,67.0139578064081,61.2931988990917,60.9889678467,61.3482200315912,60.6956669345634,60.4657739623467,60.9248450809331,60.4364235221634,60.3290604695359,61.0059654323406,60.9216349740899,59.968973197382,59.3576020818574,58.5886318145423,60.8175776311052,60.2705301621311,58.3988911277276,61.2610028877745,60.9055624058672,60.8066023417319,60.4198504139205,60.154894231956,60.0697505158151,59.9220982186114,59.7610204229216,59.6557197342934,59.2243608764146,59.1559788668864,59.1035878606538,58.7831592492831,58.7295861596589,58.6867265424705 19 | total mean compression rate,61.6831574522753,56.902702979689,56.5897517076318,56.9028087089666,56.3324910450939,56.1031240254565,56.4380595268791,56.0058563333357,55.895690077368,56.4909353016295,56.4473208665477,55.4510418643857,54.9867027510907,54.3179113103974,56.3868690504802,55.8155901560271,54.3001956086339,56.7345745492479,56.3973507142287,56.2948689255441,55.9240088078764,55.7044253460296,55.6118144314479,55.5034085314469,55.3599518195236,55.258530857357,54.9477136057016,54.891530303839,54.8337412808302,54.5921489021501,54.5418607929781,54.4979866739821 20 | Time,2025-01-26 05:32:47 21 | CPU,"AMD64 Family 26 Model 68 Stepping 0, AuthenticAMD" 22 | -------------------------------------------------------------------------------- /evaluation/codec_comparison_summery_sse41.csv: -------------------------------------------------------------------------------- 1 | ,SRLA -m 8 -V 0 -B 4096,SRLA -m 8 -V 1 -B 4096,SRLA -m 8 -V 2 -B 4096,SRLA -m 8 -V 0 -B 8192,SRLA -m 8 -V 1 -B 8192,SRLA -m 8 -V 2 -B 8192,SRLA -m 8 -V 0 -B 16384,SRLA -m 8 -V 1 -B 16384,SRLA -m 8 -V 2 -B 16384,SRLA -m 12 -V 0 -B 4096,SRLA -m 12 -V 1 -B 4096,SRLA -m 12 -V 2 -B 4096,SRLA -m 12 -V 0 -B 8192,SRLA -m 12 -V 1 -B 8192,SRLA -m 12 -V 2 -B 8192,SRLA -m 12 -V 0 -B 16384,SRLA -m 12 -V 1 -B 16384,SRLA -m 12 -V 2 -B 16384,SRLA -m 16 -V 0 -B 4096,SRLA -m 16 -V 1 -B 4096,SRLA -m 16 -V 2 -B 4096,SRLA -m 16 -V 0 -B 8192,SRLA -m 16 -V 1 -B 8192,SRLA -m 16 -V 2 -B 8192,SRLA -m 16 -V 0 -B 16384,SRLA -m 16 -V 1 -B 16384,SRLA -m 16 -V 2 -B 16384 2 | classic mean encode time,0.5079214716087597,1.2436615325143372,2.5118464959175304,0.4968775048304511,1.1870160502804714,2.3401203385634344,0.500563979915631,1.1677190097127206,2.2998478673491975,0.5937750809649968,1.474737684519934,3.012489759175713,0.5671361935243394,1.3893683953027083,2.7765360921694344,0.5694657982868723,1.381020632081599,2.7277948804323024,0.7615562457883857,2.0792128716204377,4.544358072734918,0.7147396354431259,1.86327515684457,3.8139764835359955,0.7147034672824149,1.817097248083143,3.621895003620751 3 | genre mean encode time,0.5170253158923765,1.2501361740919172,2.4903830863630216,0.5087599163883283,1.1925119733704526,2.338080248095802,0.5210301722166939,1.1966557743483437,2.318298403317239,0.5742149624121936,1.4212677146716637,2.933627616330158,0.5623395650686845,1.3420790344239222,2.659006510343863,0.5904633123696849,1.3761119768421866,2.6707380597198482,0.716349288128869,1.992056483235385,4.4247791276172235,0.6632889318081944,1.7126350636462069,3.568441873469968,0.7105090267318541,1.7067641532928386,3.389673862201272 4 | jazz mean encode time,0.5079249128982686,1.2160430807435159,2.4354992671716844,0.4940453874120498,1.1584611449716313,2.2785767953674654,0.5028966118677625,1.1599964083452867,2.254944464930948,0.5603243863783886,1.3843712890541735,2.860636270499653,0.5444177146354412,1.3024892660555123,2.5903408877097394,0.5662047388727677,1.3224349330177576,2.5809442406996186,0.7033097406826943,1.9421404642632192,4.337744875794813,0.6442011452680961,1.6597287717222489,3.4681574850145114,0.676477895349208,1.63347699566496,3.2663505485312805 5 | popular mean encode time,0.5343130133434402,1.2634874679130579,2.5144907749724945,0.5171222775841116,1.2100372383025657,2.3657218670023656,0.5256865059221411,1.2094638657345187,2.351318131048168,0.5848813537912065,1.4422345482256744,2.9503856163335938,0.5735845015148431,1.3711198937084292,2.705825996920706,0.6025104382376103,1.4083447754667113,2.7255406856202495,0.7279412899702118,2.0138772704809957,4.452576323444138,0.6795205361807108,1.7474141407611476,3.631712873148887,0.7277159323873887,1.7519426478953048,3.4701280577336684 6 | right mean encode time,0.5401565903006547,1.2728481372486793,2.536767992015935,0.5210057814122733,1.223214322885373,2.3958309517251206,0.5232734500402507,1.2208275814044522,2.3664813763839785,0.6040039092080101,1.4924952033736736,3.0291604304673623,0.5959583440468618,1.4376217402090716,2.8281120254106753,0.6116999574323432,1.463417873471773,2.845748596256594,0.7585968699574327,2.061261154778803,4.497654502241748,0.731269684562887,1.8648311640745647,3.8057209947029706,0.7775440596601847,1.9098525890055038,3.743903640020319 7 | total mean encode time,0.520289917303011,1.2466782109205745,2.4914457907283603,0.5067653697063735,1.191055809358029,2.3367983267874726,0.5150070725428515,1.1889092182193997,2.313753341841185,0.5794282253472606,1.4325636737804481,2.9409131602993597,0.5646663445144519,1.3559183966629924,2.6878963421793287,0.5864951681887636,1.3801666197252762,2.687717998387568,0.7270633214624671,2.005810590881612,4.4370356332815435,0.6768124795226219,1.7457405186904158,3.6203020067278726,0.7131053388904603,1.7353173169502993,3.447455228580996 8 | classic mean decode time,0.13032645395782627,0.13232012848494845,0.1343152483444794,0.13574647930212297,0.13486508522888735,0.13386123280581158,0.13716850942682252,0.13570261998180003,0.13488242445911222,0.15271417965084122,0.15097065891363093,0.15058420855778484,0.1616248654044224,0.15893034474691906,0.15707386714766317,0.16694331541104512,0.16427100739033496,0.16204075573610133,0.1691815883800822,0.16736985279521144,0.16770606563227747,0.1966459586985132,0.19230428333411895,0.19042972906480138,0.21717877524676385,0.21001243158041677,0.20556395602006572 9 | genre mean decode time,0.13169016172786116,0.13193192091088018,0.13125482401872382,0.13728481122698985,0.1339124778026947,0.1325458971248075,0.14229698681041092,0.13784376647306307,0.13410483785351415,0.14056782418455074,0.13780222555223676,0.13836874999327223,0.15480621405945735,0.14602387305482897,0.14336700379701361,0.17228369659333728,0.1587631928268294,0.15011961730656512,0.14310112815069123,0.14093688031507273,0.14043197360119894,0.1683954765736395,0.15645497898515748,0.15372981701167834,0.21161503876411092,0.18280089098064067,0.16800838507885416 10 | jazz mean decode time,0.1290273139852927,0.12876885461412896,0.1283751308145592,0.133230295274419,0.1300792477557288,0.12953185549491875,0.13714020948696212,0.13288004091162348,0.13072931008098412,0.13593242119361684,0.13418156426770553,0.13369838052619362,0.14847873958799068,0.14158433348766478,0.14009540756695268,0.16268493591737102,0.15163680120558404,0.14543087538238497,0.13888819495120983,0.13662107658003633,0.1365147051891092,0.16095625490691462,0.15035240079078865,0.148320294223016,0.1970717778897571,0.17231035968042022,0.16210707804711383 11 | popular mean decode time,0.13502368430430028,0.13443710141969922,0.13345635400361433,0.1401713052339676,0.13594205476873017,0.1350206259663551,0.14442776661055004,0.1395811236880632,0.13688632560544695,0.14385308940785557,0.14166719973912184,0.14140279599385075,0.16033408994562198,0.15051328271738867,0.14788932551892559,0.17831179642302925,0.16500114764098692,0.15459629855562038,0.14730661498113803,0.14539366421140099,0.14483772710279225,0.17683930225152772,0.16204857005101242,0.15919982997455454,0.2224398749356084,0.19295929923662375,0.17579360638710262 12 | right mean decode time,0.14199169986419796,0.14040176300526924,0.14033632953433053,0.14604002246222705,0.14255935764118796,0.1416593463004228,0.14873352223043393,0.14581281244258673,0.14277692608425474,0.1575394154492115,0.15491251129563552,0.1566189217363786,0.17628749615898281,0.16759498945040321,0.16630698335597138,0.1893597554872137,0.17983399126622196,0.17272346713521375,0.16487950194738252,0.1629811351223833,0.1629248246892321,0.20585014839747326,0.1939038212724041,0.19204786054931827,0.251613824163873,0.22720134043027704,0.2162929756100245 13 | total mean decode time,0.13258286346069315,0.13260692056330206,0.13237894851462217,0.13757407521704254,0.1343879435540972,0.13344212326297325,0.14135248842792184,0.13741600008693955,0.1348904212447399,0.14362960986971,0.14145486206490246,0.14144808003129647,0.15760935960620093,0.14994677364018577,0.14780293662168548,0.1721909396194614,0.16135199471684783,0.15389424743815036,0.1491291648896684,0.1470924673721702,0.1468339484773821,0.17640865301748698,0.16514440979401843,0.16274485186031218,0.21519217285256956,0.19093743451385786,0.17845552764809414 14 | classic mean compression rate,43.104015821846275,43.04184350431439,43.00876966876373,43.13788837212982,42.97706807731718,42.8992300407918,43.33536228318688,43.082184046947305,42.91705905048857,42.605993651739645,42.55882891836379,42.527882615524405,42.527652337998354,42.38733132821163,42.313703584892494,42.728567603372596,42.446257350533614,42.28583624946975,42.368611343218554,42.33086939237221,42.302922606016786,42.07094331423846,41.973159371167654,41.90826184266004,42.15121755100019,41.92054910851215,41.78329890635113 15 | genre mean compression rate,57.99215031862793,57.689950911549396,57.55264430328433,58.5003388319678,57.91412327443288,57.601919119574006,59.11645568992395,58.431229792331074,57.87338705065569,57.856227365485516,57.56370017351936,57.425362542437085,58.30952936409208,57.74396503490173,57.43772985870987,58.90243483216717,58.223267776688,57.68327455661832,57.826610245881284,57.535843423779745,57.39751799616774,58.22749251266348,57.68058779414165,57.377445891250126,58.74893709543132,58.110733886621375,57.59289015777845 16 | jazz mean compression rate,47.53257559475198,47.31377325242089,47.20937454951108,47.874603818937665,47.41869439900724,47.18156750405196,48.45388535554955,47.80910269478003,47.35913972423661,47.382344368280165,47.17379955273885,47.06975604102659,47.652840955369165,47.22030341060829,46.98747973031014,48.20680607563614,47.56812319383825,47.13313925317431,47.351273709024305,47.14498858881675,47.041116642485385,47.56426972406471,47.15333586859629,46.92255527146289,48.03006641205136,47.44799722286784,47.034200895219676 17 | popular mean compression rate,67.4323270229136,67.15364875898399,67.01763256064466,67.93423637942594,67.3630968676047,67.06865262409801,68.52612149471517,67.86663951402286,67.3234010713422,67.3115382627723,67.04102465511602,66.90439432722562,67.74343966684009,67.2029558374986,66.91243994990663,68.29885806355898,67.65639816141736,67.14114583328713,67.28295032076562,67.0140347960076,66.8773324149487,67.6571985962991,67.13937744504304,66.85015983821486,68.12878515310513,67.53523506044016,67.04632612135683 18 | right mean compression rate,60.24256546483743,60.06990182697583,59.98685488304166,60.518927676835126,60.13615937237831,59.94726607851394,61.0206346816802,60.45480094400534,60.08312776925462,59.96068541491677,59.796562330048054,59.713582381794886,60.1043705897572,59.75313364308109,59.56652683469174,60.55487521458383,60.002705532578716,59.6528805722249,59.8916342081859,59.72905512270939,59.64597654265336,59.89553850849568,59.57225733158709,59.386914461844206,60.19934055376522,59.7123673412038,59.38488836593217 19 | total mean compression rate,56.13789547115424,55.9104788317617,55.80201483364006,56.51189432686985,56.04414000883554,55.801644897862815,57.036340068289846,56.44661310627793,55.995280367130974,55.93444855998881,55.71716484392601,55.608711780500016,56.23026224768222,55.787587372564076,55.549502374096335,56.72928207832717,56.143819091044875,55.71089628328017,55.8685170453779,55.65428211804763,55.54632695375076,56.07601415775246,55.65841915935959,55.42341239609955,56.48258794323452,55.94765076481924,55.538100153583436 20 | -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_16384_classic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_16384_classic.png -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_16384_genre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_16384_genre.png -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_16384_jazz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_16384_jazz.png -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_16384_popular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_16384_popular.png -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_16384_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_16384_right.png -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_16384_total.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_16384_total.png -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_4096_classic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_4096_classic.png -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_4096_genre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_4096_genre.png -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_4096_jazz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_4096_jazz.png -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_4096_popular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_4096_popular.png -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_4096_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_4096_right.png -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_4096_total.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_4096_total.png -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_8192_classic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_8192_classic.png -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_8192_genre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_8192_genre.png -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_8192_jazz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_8192_jazz.png -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_8192_popular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_8192_popular.png -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_8192_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_8192_right.png -------------------------------------------------------------------------------- /evaluation/decodespeed_vs_compressionrate_8192_total.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/decodespeed_vs_compressionrate_8192_total.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_16384_classic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_16384_classic.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_16384_genre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_16384_genre.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_16384_jazz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_16384_jazz.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_16384_popular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_16384_popular.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_16384_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_16384_right.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_16384_total.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_16384_total.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_4096_classic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_4096_classic.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_4096_genre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_4096_genre.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_4096_jazz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_4096_jazz.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_4096_popular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_4096_popular.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_4096_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_4096_right.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_4096_total.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_4096_total.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_8192_classic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_8192_classic.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_8192_genre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_8192_genre.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_8192_jazz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_8192_jazz.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_8192_popular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_8192_popular.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_8192_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_8192_right.png -------------------------------------------------------------------------------- /evaluation/encodespeed_vs_compressionrate_8192_total.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/evaluation/encodespeed_vs_compressionrate_8192_total.png -------------------------------------------------------------------------------- /evaluation/plot_codec_performance_graph.py: -------------------------------------------------------------------------------- 1 | " コーデック評価グラフの作成 " 2 | import pandas as pd 3 | import matplotlib 4 | import matplotlib.pyplot as plt 5 | from adjustText import adjust_text 6 | 7 | # type3 font 回避(tex使用) 8 | matplotlib.rcParams['text.usetex'] = True 9 | matplotlib.rcParams['text.latex.preamble'] = '\\usepackage{sfmath}' 10 | # フォントサイズ一括設定 11 | matplotlib.rcParams["font.size"] = 12 12 | matplotlib.rcParams['pgf.texsystem'] = 'lualatex' 13 | 14 | OTHER_CODEC_LABEL_PREFIXES = ['FLAC', 'WavPack', 'TTA', 'Monkey\'s Audio', 'MPEG4-ALS', 'TAK'] 15 | COLORLIST = ['crimson', 'g', 'b', 'c', 'm', 'k', 'purple', 'red', 'orange'] 16 | CATEGORIES = ['classic', 'genre', 'jazz', 'popular', 'right', 'total'] 17 | 18 | AVOID_LABEL_LIST = ['FLAC -0', 'WavPack -x4', 'WavPack -h -x4', 'WavPack -hh -x4', 'Monkey\'s Audio -c4000', 'MPEG4-ALS -b', 'MPEG4-ALS -7', 'TAK -p0e', 'TAK -p0', 'TAK -p1e', 'TAK -p1', 'TAK -p2e', 'TAK -p2', 'TAK -p3e', 'TAK -p3','TAK -p4e', 'TAK -p4'] 19 | 20 | def _is_avoid_label(label): 21 | for content in AVOID_LABEL_LIST: 22 | if label == content: 23 | return True 24 | return False 25 | 26 | if __name__ == "__main__": 27 | other_codecs_df = pd.read_csv('codec_comparison_summery_other_codecs.csv', index_col=0) 28 | srla_codecs_df = pd.read_csv('codec_comparison_summery.csv', index_col=0) 29 | avx2_srla_codecs_df = pd.read_csv('codec_comparison_summery_avx2.csv', index_col=0) 30 | 31 | for block_size in [4096, 8192, 16384]: 32 | # デコード速度 v.s. 圧縮率グラフ 33 | for category in CATEGORIES: 34 | texts = [] 35 | plt.cla() 36 | # 他コーデック 37 | for inx, cprefix in enumerate(OTHER_CODEC_LABEL_PREFIXES): 38 | line = [[], []] 39 | for label in other_codecs_df.keys(): 40 | if _is_avoid_label(label) is True: 41 | continue 42 | if label.startswith(cprefix): 43 | decode_time = other_codecs_df.at[f'{category} mean decode time', label] 44 | compress_rate = other_codecs_df.at[f'{category} mean compression rate', label] 45 | texts.append(plt.text(decode_time, compress_rate, label[len(cprefix):], size=10)) 46 | line[0].append(decode_time) 47 | line[1].append(compress_rate) 48 | plt.plot(line[0], line[1], color=COLORLIST[inx], label=cprefix, marker='o') 49 | # SRLA 50 | for div_index, div in enumerate([0, 2]): 51 | line = [[], []] 52 | for label in srla_codecs_df.keys(): 53 | if label.startswith('SRLA'): 54 | if not str(block_size) in label or not f'-V {div}' in label: 55 | continue 56 | option_prefix = label[len('SRLA'):label.index('V') - 1] 57 | decode_time = float(srla_codecs_df.at[f'{category} mean decode time', label]) 58 | compress_rate = float(srla_codecs_df.at[f'{category} mean compression rate', label]) 59 | texts.append(plt.text(decode_time, compress_rate, option_prefix, size=10)) 60 | line[0].append(decode_time) 61 | line[1].append(compress_rate) 62 | plt.plot(line[0], line[1], color=COLORLIST[len(OTHER_CODEC_LABEL_PREFIXES) + div_index], label=f'SRLA V={div}', marker='^') 63 | # AVX2 SRLA 64 | for div_index, div in enumerate([0, 2]): 65 | line = [[], []] 66 | for label in avx2_srla_codecs_df.keys(): 67 | if label.startswith('SRLA'): 68 | if not str(block_size) in label or not f'-V {div}' in label: 69 | continue 70 | option_prefix = label[len('SRLA'):label.index('V') - 1] 71 | decode_time = float(avx2_srla_codecs_df.at[f'{category} mean decode time', label]) 72 | compress_rate = float(avx2_srla_codecs_df.at[f'{category} mean compression rate', label]) 73 | texts.append(plt.text(decode_time, compress_rate, option_prefix, size=10)) 74 | line[0].append(decode_time) 75 | line[1].append(compress_rate) 76 | plt.plot(line[0], line[1], color=COLORLIST[len(OTHER_CODEC_LABEL_PREFIXES) + div_index], label=f'AVX2 SRLA V={div}', marker='^', linestyle='--') 77 | 78 | adjust_text(texts) 79 | plt.title(f'Decoding speed v.s. compression rate for {category} blocksize:{block_size}') 80 | plt.xlabel('Average decoding speed (\%)') 81 | plt.ylabel('Average compression rate (\%)') 82 | plt.legend(ncols=2) 83 | plt.grid() 84 | if category == 'total': 85 | plt.ylim(ymin=53.5) 86 | plt.tight_layout() 87 | plt.savefig(f'decodespeed_vs_compressionrate_{block_size}_{category}.png') 88 | 89 | # エンコード速度 v.s. 圧縮率グラフ 90 | for category in CATEGORIES: 91 | texts = [] 92 | plt.cla() 93 | # 他コーデック 94 | for inx, cprefix in enumerate(OTHER_CODEC_LABEL_PREFIXES): 95 | line = [[], []] 96 | for label in other_codecs_df.keys(): 97 | if _is_avoid_label(label) is True: 98 | continue 99 | if label.startswith(cprefix): 100 | encode_time = other_codecs_df.at[f'{category} mean encode time', label] 101 | compress_rate = other_codecs_df.at[f'{category} mean compression rate', label] 102 | texts.append(plt.text(encode_time, compress_rate, label[len(cprefix):], size=10)) 103 | line[0].append(encode_time) 104 | line[1].append(compress_rate) 105 | plt.plot(line[0], line[1], color=COLORLIST[inx], label=cprefix, marker='o') 106 | # SRLA 107 | for div_index, div in enumerate([0, 2]): 108 | line = [[], []] 109 | for label in srla_codecs_df.keys(): 110 | if label.startswith('SRLA'): 111 | if not str(block_size) in label or not f'-V {div}' in label: 112 | continue 113 | option_prefix = label[len('SRLA'):label.index('V') - 1] 114 | encode_time = srla_codecs_df.at[f'{category} mean encode time', label] 115 | compress_rate = srla_codecs_df.at[f'{category} mean compression rate', label] 116 | texts.append(plt.text(encode_time, compress_rate, option_prefix, size=10)) 117 | line[0].append(encode_time) 118 | line[1].append(compress_rate) 119 | plt.plot(line[0], line[1], color=COLORLIST[len(OTHER_CODEC_LABEL_PREFIXES) + div_index], label=f'SRLA V={div}', marker='^') 120 | 121 | adjust_text(texts) 122 | plt.title(f'Encoding speed v.s. compression rate for {category} blocksize:{block_size}') 123 | plt.xlabel('Average encoding speed (\%)') 124 | plt.ylabel('Average compression rate (\%)') 125 | plt.legend(ncols=2) 126 | plt.grid() 127 | plt.tight_layout() 128 | plt.savefig(f'encodespeed_vs_compressionrate_{block_size}_{category}.png') 129 | -------------------------------------------------------------------------------- /include/srla.h: -------------------------------------------------------------------------------- 1 | #ifndef SRLA_H_INCLUDED 2 | #define SRLA_H_INCLUDED 3 | 4 | #include "srla_stdint.h" 5 | 6 | /* フォーマットバージョン */ 7 | #define SRLA_FORMAT_VERSION 6 8 | 9 | /* コーデックバージョン */ 10 | #define SRLA_CODEC_VERSION 9 11 | 12 | /* ヘッダサイズ */ 13 | #define SRLA_HEADER_SIZE 29 14 | 15 | /* 処理可能な最大チャンネル数 */ 16 | #define SRLA_MAX_NUM_CHANNELS 8 17 | 18 | /* 最大係数次数 */ 19 | #define SRLA_MAX_COEFFICIENT_ORDER 255 20 | 21 | /* パラメータプリセット数 */ 22 | #define SRLA_NUM_PARAMETER_PRESETS 7 23 | 24 | 25 | /* API結果型 */ 26 | typedef enum SRLAApiResultTag { 27 | SRLA_APIRESULT_OK = 0, /* 成功 */ 28 | SRLA_APIRESULT_INVALID_ARGUMENT, /* 無効な引数 */ 29 | SRLA_APIRESULT_INVALID_FORMAT, /* 不正なフォーマット */ 30 | SRLA_APIRESULT_INSUFFICIENT_BUFFER, /* バッファサイズが足りない */ 31 | SRLA_APIRESULT_INSUFFICIENT_DATA, /* データが足りない */ 32 | SRLA_APIRESULT_PARAMETER_NOT_SET, /* パラメータがセットされてない */ 33 | SRLA_APIRESULT_DETECT_DATA_CORRUPTION, /* データ破損を検知した */ 34 | SRLA_APIRESULT_NG /* 分類不能な失敗 */ 35 | } SRLAApiResult; 36 | 37 | /* ヘッダ情報 */ 38 | struct SRLAHeader { 39 | uint32_t format_version; /* フォーマットバージョン */ 40 | uint32_t codec_version; /* エンコーダバージョン */ 41 | uint16_t num_channels; /* チャンネル数 */ 42 | uint32_t num_samples; /* 1チャンネルあたり総サンプル数 */ 43 | uint32_t sampling_rate; /* サンプリングレート */ 44 | uint16_t bits_per_sample; /* サンプルあたりビット数 */ 45 | uint32_t max_num_samples_per_block; /* ブロックあたり最大サンプル数 */ 46 | uint8_t preset; /* パラメータプリセット */ 47 | }; 48 | 49 | #endif /* SRLA_H_INCLUDED */ 50 | -------------------------------------------------------------------------------- /include/srla_decoder.h: -------------------------------------------------------------------------------- 1 | #ifndef SRLA_DECODER_H_INCLUDED 2 | #define SRLA_DECODER_H_INCLUDED 3 | 4 | #include "srla.h" 5 | #include "srla_stdint.h" 6 | 7 | /* デコーダコンフィグ */ 8 | struct SRLADecoderConfig { 9 | uint32_t max_num_channels; /* 最大チャンネル数 */ 10 | uint32_t max_num_parameters; /* 最大パラメータ数 */ 11 | uint8_t check_checksum; /* チェックサムによるデータ破損検査を行うか? 1:ON それ以外:OFF */ 12 | }; 13 | 14 | /* デコーダハンドル */ 15 | struct SRLADecoder; 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif /* __cplusplus */ 20 | 21 | /* ヘッダデコード */ 22 | SRLAApiResult SRLADecoder_DecodeHeader( 23 | const uint8_t *data, uint32_t data_size, struct SRLAHeader *header); 24 | 25 | /* デコーダハンドルの作成に必要なワークサイズの計算 */ 26 | int32_t SRLADecoder_CalculateWorkSize(const struct SRLADecoderConfig *condig); 27 | 28 | /* デコーダハンドルの作成 */ 29 | struct SRLADecoder* SRLADecoder_Create(const struct SRLADecoderConfig *condig, void *work, int32_t work_size); 30 | 31 | /* デコーダハンドルの破棄 */ 32 | void SRLADecoder_Destroy(struct SRLADecoder *decoder); 33 | 34 | /* デコーダにヘッダをセット */ 35 | SRLAApiResult SRLADecoder_SetHeader( 36 | struct SRLADecoder *decoder, const struct SRLAHeader *header); 37 | 38 | /* 単一データブロックデコード */ 39 | SRLAApiResult SRLADecoder_DecodeBlock( 40 | struct SRLADecoder *decoder, 41 | const uint8_t *data, uint32_t data_size, 42 | int32_t **buffer, uint32_t buffer_num_channels, uint32_t buffer_num_samples, 43 | uint32_t *decode_size, uint32_t *num_decode_samples); 44 | 45 | /* ヘッダを含めて全ブロックデコード */ 46 | SRLAApiResult SRLADecoder_DecodeWhole( 47 | struct SRLADecoder *decoder, 48 | const uint8_t *data, uint32_t data_size, 49 | int32_t **buffer, uint32_t buffer_num_channels, uint32_t buffer_num_samples); 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif /* __cplusplus */ 54 | 55 | #endif /* SRLA_DECODER_H_INCLUDED */ 56 | -------------------------------------------------------------------------------- /include/srla_encoder.h: -------------------------------------------------------------------------------- 1 | #ifndef SRLA_ENCODER_H_INCLUDED 2 | #define SRLA_ENCODER_H_INCLUDED 3 | 4 | #include "srla.h" 5 | #include "srla_stdint.h" 6 | 7 | /* エンコードパラメータ */ 8 | struct SRLAEncodeParameter { 9 | uint16_t num_channels; /* 入力波形のチャンネル数 */ 10 | uint16_t bits_per_sample; /* 入力波形のサンプルあたりビット数 */ 11 | uint32_t sampling_rate; /* 入力波形のサンプリングレート */ 12 | uint32_t min_num_samples_per_block; /* ブロックあたり最小サンプル数 */ 13 | uint32_t max_num_samples_per_block; /* ブロックあたり最大サンプル数 */ 14 | uint8_t preset; /* エンコードパラメータプリセット */ 15 | }; 16 | 17 | /* エンコーダコンフィグ */ 18 | struct SRLAEncoderConfig { 19 | uint32_t max_num_channels; /* 最大チャンネル数 */ 20 | uint32_t min_num_samples_per_block; /* ブロックあたりサンプル数の下限値 */ 21 | uint32_t max_num_samples_per_block; /* ブロックあたりサンプル数の上限値 */ 22 | uint32_t max_num_parameters; /* 最大のパラメータ数 */ 23 | }; 24 | 25 | /* エンコーダハンドル */ 26 | struct SRLAEncoder; 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif /* __cplusplus */ 31 | 32 | /* ヘッダエンコード */ 33 | SRLAApiResult SRLAEncoder_EncodeHeader( 34 | const struct SRLAHeader *header, uint8_t *data, uint32_t data_size); 35 | 36 | /* エンコーダハンドル作成に必要なワークサイズ計算 */ 37 | int32_t SRLAEncoder_CalculateWorkSize(const struct SRLAEncoderConfig *config); 38 | 39 | /* エンコーダハンドル作成 */ 40 | struct SRLAEncoder *SRLAEncoder_Create(const struct SRLAEncoderConfig *config, void *work, int32_t work_size); 41 | 42 | /* エンコーダハンドルの破棄 */ 43 | void SRLAEncoder_Destroy(struct SRLAEncoder *encoder); 44 | 45 | /* エンコードパラメータの設定 */ 46 | SRLAApiResult SRLAEncoder_SetEncodeParameter( 47 | struct SRLAEncoder *encoder, const struct SRLAEncodeParameter *parameter); 48 | 49 | /* 単一データブロックサイズ計算 */ 50 | SRLAApiResult SRLAEncoder_ComputeBlockSize( 51 | struct SRLAEncoder *encoder, const int32_t *const *input, uint32_t num_samples, 52 | uint32_t *output_size); 53 | 54 | /* 単一データブロックエンコード */ 55 | SRLAApiResult SRLAEncoder_EncodeBlock( 56 | struct SRLAEncoder *encoder, 57 | const int32_t *const *input, uint32_t num_samples, 58 | uint8_t *data, uint32_t data_size, uint32_t *output_size); 59 | 60 | /* 最適なブロック分割探索を含めたエンコード */ 61 | SRLAApiResult SRLAEncoder_EncodeOptimalPartitionedBlock( 62 | struct SRLAEncoder *encoder, 63 | const int32_t *const *input, uint32_t num_samples, 64 | uint8_t *data, uint32_t data_size, uint32_t *output_size); 65 | 66 | /* ヘッダ含めファイル全体をエンコード */ 67 | SRLAApiResult SRLAEncoder_EncodeWhole( 68 | struct SRLAEncoder *encoder, 69 | const int32_t *const *input, uint32_t num_samples, 70 | uint8_t *data, uint32_t data_size, uint32_t *output_size, uint8_t variable_block); 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif /* __cplusplus */ 75 | 76 | #endif /* SRLA_ENCODER_H_INCLUDED */ 77 | -------------------------------------------------------------------------------- /include/srla_stdint.h: -------------------------------------------------------------------------------- 1 | #ifndef SRLA_STDINT_H_INCLUDED 2 | #define SRLA_STDINT_H_INCLUDED 3 | 4 | /* stdint.hが無い環境向けに 5 | * stdint.h相当の型定義を行う */ 6 | 7 | /* 現在のところは必ずstdint.hを使用する */ 8 | /* 困った場合に定義を追加する */ 9 | #include 10 | 11 | #endif /* SRLA_STDINT_H_INCLUDED */ 12 | -------------------------------------------------------------------------------- /libs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | add_subdirectory(bit_stream) 4 | add_subdirectory(byte_array) 5 | add_subdirectory(command_line_parser) 6 | add_subdirectory(srla_coder) 7 | add_subdirectory(srla_decoder) 8 | add_subdirectory(srla_encoder) 9 | add_subdirectory(srla_internal) 10 | add_subdirectory(fft) 11 | add_subdirectory(lpc) 12 | add_subdirectory(static_huffman) 13 | add_subdirectory(wav) 14 | -------------------------------------------------------------------------------- /libs/bit_stream/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # プロジェクト名 6 | project(BitStream C) 7 | 8 | # ライブラリ名 9 | set(LIB_NAME bit_stream) 10 | 11 | # 静的ライブラリ指定 12 | add_library(${LIB_NAME} STATIC) 13 | 14 | # ソースディレクトリ 15 | add_subdirectory(src) 16 | 17 | # インクルードパス 18 | target_include_directories(${LIB_NAME} 19 | PRIVATE 20 | ${PROJECT_ROOT_PATH}/include 21 | PUBLIC 22 | ${CMAKE_CURRENT_SOURCE_DIR}/include 23 | ) 24 | 25 | # コンパイルオプション 26 | if(MSVC) 27 | target_compile_options(${LIB_NAME} PRIVATE /W4) 28 | else() 29 | target_compile_options(${LIB_NAME} PRIVATE -Wall -Wextra -Wpedantic -Wformat=2 -Wstrict-aliasing=2 -Wconversion -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition) 30 | set(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -DDEBUG") 31 | set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") 32 | endif() 33 | set_target_properties(${LIB_NAME} 34 | PROPERTIES 35 | C_STANDARD 90 C_EXTENSIONS OFF 36 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 37 | ) 38 | -------------------------------------------------------------------------------- /libs/bit_stream/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${LIB_NAME} 2 | PRIVATE 3 | ${CMAKE_CURRENT_SOURCE_DIR}/bit_stream.c 4 | ) 5 | -------------------------------------------------------------------------------- /libs/byte_array/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | # プロジェクト名 4 | project(ByteArray C) 5 | 6 | # ライブラリ名 7 | set(LIB_NAME byte_array) 8 | 9 | # ライブラリ 10 | add_library(${LIB_NAME} INTERFACE) 11 | 12 | # インクルードパス 13 | target_include_directories(${LIB_NAME} 14 | INTERFACE 15 | ${CMAKE_CURRENT_SOURCE_DIR}/include 16 | ) 17 | -------------------------------------------------------------------------------- /libs/byte_array/include/byte_array.h: -------------------------------------------------------------------------------- 1 | #ifndef BYTEARRAY_H_INCLUDED 2 | #define BYTEARRAY_H_INCLUDED 3 | 4 | #include 5 | 6 | /* 1バイト読み出し */ 7 | #define ByteArray_ReadUint8(p_array)\ 8 | (uint8_t)((p_array)[0]) 9 | 10 | /* 2バイト読み出し(ビッグエンディアン) */ 11 | #define ByteArray_ReadUint16BE(p_array)\ 12 | (uint16_t)(\ 13 | (((uint16_t)((p_array)[0])) << 8) |\ 14 | (((uint16_t)((p_array)[1])) << 0)\ 15 | ) 16 | 17 | /* 3バイト読み出し(ビッグエンディアン) */ 18 | #define ByteArray_ReadUint24BE(p_array)\ 19 | (uint32_t)(\ 20 | (((uint32_t)((p_array)[0])) << 16) |\ 21 | (((uint32_t)((p_array)[1])) << 8) |\ 22 | (((uint32_t)((p_array)[2])) << 0)\ 23 | ) 24 | 25 | /* 4バイト読み出し(ビッグエンディアン) */ 26 | #define ByteArray_ReadUint32BE(p_array)\ 27 | (uint32_t)(\ 28 | (((uint32_t)((p_array)[0])) << 24) |\ 29 | (((uint32_t)((p_array)[1])) << 16) |\ 30 | (((uint32_t)((p_array)[2])) << 8) |\ 31 | (((uint32_t)((p_array)[3])) << 0)\ 32 | ) 33 | 34 | /* 2バイト読み出し(リトルエンディアン) */ 35 | #define ByteArray_ReadUint16LE(p_array)\ 36 | (uint16_t)(\ 37 | (((uint16_t)((p_array)[0])) << 0) |\ 38 | (((uint16_t)((p_array)[1])) << 8)\ 39 | ) 40 | 41 | /* 3バイト読み出し(リトルエンディアン) */ 42 | #define ByteArray_ReadUint24LE(p_array)\ 43 | (uint32_t)(\ 44 | (((uint32_t)((p_array)[0])) << 0) |\ 45 | (((uint32_t)((p_array)[1])) << 8) |\ 46 | (((uint32_t)((p_array)[2])) << 16)\ 47 | ) 48 | 49 | /* 4バイト読み出し(リトルエンディアン) */ 50 | #define ByteArray_ReadUint32LE(p_array)\ 51 | (uint32_t)(\ 52 | (((uint32_t)((p_array)[0])) << 0) |\ 53 | (((uint32_t)((p_array)[1])) << 8) |\ 54 | (((uint32_t)((p_array)[2])) << 16) |\ 55 | (((uint32_t)((p_array)[3])) << 24)\ 56 | ) 57 | 58 | /* 1バイト取得 */ 59 | #define ByteArray_GetUint8(p_array, p_u8val)\ 60 | do {\ 61 | (*(p_u8val)) = ByteArray_ReadUint8(p_array);\ 62 | (p_array) += 1;\ 63 | } while (0); 64 | 65 | /* 2バイト取得(ビッグエンディアン) */ 66 | #define ByteArray_GetUint16BE(p_array, p_u16val)\ 67 | do {\ 68 | (*(p_u16val)) = ByteArray_ReadUint16BE(p_array);\ 69 | (p_array) += 2;\ 70 | } while (0); 71 | 72 | /* 3バイト取得(ビッグエンディアン) */ 73 | #define ByteArray_GetUint24BE(p_array, p_u32val)\ 74 | do {\ 75 | (*(p_u32val)) = ByteArray_ReadUint24BE(p_array);\ 76 | (p_array) += 3;\ 77 | } while (0); 78 | 79 | /* 4バイト取得(ビッグエンディアン) */ 80 | #define ByteArray_GetUint32BE(p_array, p_u32val)\ 81 | do {\ 82 | (*(p_u32val)) = ByteArray_ReadUint32BE(p_array);\ 83 | (p_array) += 4;\ 84 | } while (0); 85 | 86 | /* 2バイト取得(リトルエンディアン) */ 87 | #define ByteArray_GetUint16LE(p_array, p_u16val)\ 88 | do {\ 89 | (*(p_u16val)) = ByteArray_ReadUint16LE(p_array);\ 90 | (p_array) += 2;\ 91 | } while (0); 92 | 93 | /* 3バイト取得(リトルエンディアン) */ 94 | #define ByteArray_GetUint24LE(p_array, p_u32val)\ 95 | do {\ 96 | (*(p_u32val)) = ByteArray_ReadUint24LE(p_array);\ 97 | (p_array) += 3;\ 98 | } while (0); 99 | 100 | /* 4バイト取得(リトルエンディアン) */ 101 | #define ByteArray_GetUint32LE(p_array, p_u32val)\ 102 | do {\ 103 | (*(p_u32val)) = ByteArray_ReadUint32LE(p_array);\ 104 | (p_array) += 4;\ 105 | } while (0); 106 | 107 | /* 1バイト書き出し */ 108 | #define ByteArray_WriteUint8(p_array, u8val)\ 109 | do {\ 110 | ((p_array)[0]) = (uint8_t)(u8val);\ 111 | } while (0); 112 | 113 | /* 2バイト書き出し(ビッグエンディアン) */ 114 | #define ByteArray_WriteUint16BE(p_array, u16val)\ 115 | do {\ 116 | ((p_array)[0]) = (uint8_t)(((u16val) >> 8) & 0xFF);\ 117 | ((p_array)[1]) = (uint8_t)(((u16val) >> 0) & 0xFF);\ 118 | } while (0); 119 | 120 | /* 3バイト書き出し(ビッグエンディアン) */ 121 | #define ByteArray_WriteUint24BE(p_array, u32val)\ 122 | do {\ 123 | ((p_array)[0]) = (uint8_t)(((u32val) >> 16) & 0xFF);\ 124 | ((p_array)[1]) = (uint8_t)(((u32val) >> 8) & 0xFF);\ 125 | ((p_array)[2]) = (uint8_t)(((u32val) >> 0) & 0xFF);\ 126 | } while (0); 127 | 128 | /* 4バイト書き出し(ビッグエンディアン) */ 129 | #define ByteArray_WriteUint32BE(p_array, u32val)\ 130 | do {\ 131 | ((p_array)[0]) = (uint8_t)(((u32val) >> 24) & 0xFF);\ 132 | ((p_array)[1]) = (uint8_t)(((u32val) >> 16) & 0xFF);\ 133 | ((p_array)[2]) = (uint8_t)(((u32val) >> 8) & 0xFF);\ 134 | ((p_array)[3]) = (uint8_t)(((u32val) >> 0) & 0xFF);\ 135 | } while (0); 136 | 137 | /* 2バイト書き出し(リトルエンディアン) */ 138 | #define ByteArray_WriteUint16LE(p_array, u16val)\ 139 | do {\ 140 | ((p_array)[0]) = (uint8_t)(((u16val) >> 0) & 0xFF);\ 141 | ((p_array)[1]) = (uint8_t)(((u16val) >> 8) & 0xFF);\ 142 | } while (0); 143 | 144 | /* 3バイト書き出し(リトルエンディアン) */ 145 | #define ByteArray_WriteUint24LE(p_array, u32val)\ 146 | do {\ 147 | ((p_array)[0]) = (uint8_t)(((u32val) >> 0) & 0xFF);\ 148 | ((p_array)[1]) = (uint8_t)(((u32val) >> 8) & 0xFF);\ 149 | ((p_array)[2]) = (uint8_t)(((u32val) >> 16) & 0xFF);\ 150 | } while (0); 151 | 152 | /* 4バイト書き出し(リトルエンディアン) */ 153 | #define ByteArray_WriteUint32LE(p_array, u32val)\ 154 | do {\ 155 | ((p_array)[0]) = (uint8_t)(((u32val) >> 0) & 0xFF);\ 156 | ((p_array)[1]) = (uint8_t)(((u32val) >> 8) & 0xFF);\ 157 | ((p_array)[2]) = (uint8_t)(((u32val) >> 16) & 0xFF);\ 158 | ((p_array)[3]) = (uint8_t)(((u32val) >> 24) & 0xFF);\ 159 | } while (0); 160 | 161 | /* 1バイト出力 */ 162 | #define ByteArray_PutUint8(p_array, u8val)\ 163 | do {\ 164 | ByteArray_WriteUint8(p_array, u8val);\ 165 | (p_array) += 1;\ 166 | } while (0); 167 | 168 | /* 2バイト出力(ビッグエンディアン) */ 169 | #define ByteArray_PutUint16BE(p_array, u16val)\ 170 | do {\ 171 | ByteArray_WriteUint16BE(p_array, u16val);\ 172 | (p_array) += 2;\ 173 | } while (0); 174 | 175 | /* 3バイト出力(ビッグエンディアン) */ 176 | #define ByteArray_PutUint24BE(p_array, u32val)\ 177 | do {\ 178 | ByteArray_WriteUint24BE(p_array, u32val);\ 179 | (p_array) += 3;\ 180 | } while (0); 181 | 182 | /* 4バイト出力(ビッグエンディアン) */ 183 | #define ByteArray_PutUint32BE(p_array, u32val)\ 184 | do {\ 185 | ByteArray_WriteUint32BE(p_array, u32val);\ 186 | (p_array) += 4;\ 187 | } while (0); 188 | 189 | /* 2バイト出力(リトルエンディアン) */ 190 | #define ByteArray_PutUint16LE(p_array, u16val)\ 191 | do {\ 192 | ByteArray_WriteUint16LE(p_array, u16val);\ 193 | (p_array) += 2;\ 194 | } while (0); 195 | 196 | /* 3バイト出力(リトルエンディアン) */ 197 | #define ByteArray_PutUint24LE(p_array, u32val)\ 198 | do {\ 199 | ByteArray_WriteUint24LE(p_array, u32val);\ 200 | (p_array) += 3;\ 201 | } while (0); 202 | 203 | /* 4バイト出力(リトルエンディアン) */ 204 | #define ByteArray_PutUint32LE(p_array, u32val)\ 205 | do {\ 206 | ByteArray_WriteUint32LE(p_array, u32val);\ 207 | (p_array) += 4;\ 208 | } while (0); 209 | 210 | #endif /* BYTEARRAY_H_INCLUDED */ 211 | -------------------------------------------------------------------------------- /libs/command_line_parser/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | # プロジェクト名 4 | project(CommandLineParser C) 5 | 6 | # ライブラリ名 7 | set(LIB_NAME command_line_parser) 8 | 9 | # 静的ライブラリ指定 10 | add_library(${LIB_NAME} STATIC) 11 | 12 | # ソースディレクトリ 13 | add_subdirectory(src) 14 | 15 | # インクルードパス 16 | target_include_directories(${LIB_NAME} 17 | PUBLIC 18 | ${CMAKE_CURRENT_SOURCE_DIR}/include 19 | ) 20 | 21 | # コンパイルオプション 22 | if(MSVC) 23 | target_compile_options(${LIB_NAME} PRIVATE /W4) 24 | else() 25 | target_compile_options(${LIB_NAME} PRIVATE -Wall -Wextra -Wpedantic -Wformat=2 -Wstrict-aliasing=2 -Wconversion -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition) 26 | set(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -DDEBUG") 27 | set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") 28 | endif() 29 | set_target_properties(${LIB_NAME} 30 | PROPERTIES 31 | C_STANDARD 90 C_EXTENSIONS OFF 32 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 33 | ) 34 | -------------------------------------------------------------------------------- /libs/command_line_parser/include/command_line_parser.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMAND_LINE_PARSER_H_INCLDED 2 | #define COMMAND_LINE_PARSER_H_INCLDED 3 | 4 | #include 5 | 6 | /* 取得結果 */ 7 | typedef enum CommandLineParserResultTag { 8 | COMMAND_LINE_PARSER_RESULT_OK, /* 正常終了 */ 9 | COMMAND_LINE_PARSER_RESULT_INVALID_ARGUMENT, /* 不正な引数 */ 10 | COMMAND_LINE_PARSER_RESULT_INSUFFICIENT_OTHER_STRING_ARRAY_SIZE, /* その他の文字列が入った配列サイズが足らない */ 11 | COMMAND_LINE_PARSER_RESULT_NOT_SPECIFY_ARGUMENT_TO_OPTION, /* 引数の指定が必須のオプションで引数の指定がない */ 12 | COMMAND_LINE_PARSER_RESULT_UNKNOWN_OPTION, /* 定義にないオプションが指定された */ 13 | COMMAND_LINE_PARSER_RESULT_OPTION_MULTIPLY_SPECIFIED, /* オプションが複数回指定された */ 14 | COMMAND_LINE_PARSER_RESULT_INVALID_SPECIFICATION, /* 無効な仕様 */ 15 | COMMAND_LINE_PARSER_RESULT_INVAILD_SHORT_OPTION_ARGUMENT /* ショートオプションの引数の指定が不適切 */ 16 | } CommandLineParserResult; 17 | 18 | /* 論理定数 */ 19 | typedef enum CommandLineParserBoolTag { 20 | COMMAND_LINE_PARSER_FALSE = 0, /* 偽 */ 21 | COMMAND_LINE_PARSER_TRUE /* 真 */ 22 | } CommandLineParserBool; 23 | 24 | /* コマンドラインパーサ仕様 */ 25 | /* 補足)コマンドラインパーサ仕様の配列の最後の要素の短いオプションに0, 長いオプションにNULLを指定して下さい */ 26 | struct CommandLineParserSpecification { 27 | char short_option; /* [in] 短いオプション文字列 */ 28 | const char* long_option; /* [in] 長いオプション文字列 */ 29 | const char* description; /* [in] 引数の説明 */ 30 | CommandLineParserBool need_argument; /* [in] オプションに引数は必要か? */ 31 | const char* argument_string; /* [in,out] 得られた文字列 */ 32 | CommandLineParserBool acquired; /* [out] オプションが指定されたか? */ 33 | }; 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | /* 引数説明の印字 */ 40 | void CommandLineParser_PrintDescription( 41 | const struct CommandLineParserSpecification* clps); 42 | 43 | /* オプション名からそのオプションが指定されたか取得 */ 44 | CommandLineParserBool CommandLineParser_GetOptionAcquired( 45 | const struct CommandLineParserSpecification* clps, const char* option_name); 46 | 47 | /* オプション名からそのオプション引数を取得 */ 48 | const char* CommandLineParser_GetArgumentString( 49 | const struct CommandLineParserSpecification* clps, const char* option_name); 50 | 51 | /* 引数のパース */ 52 | CommandLineParserResult CommandLineParser_ParseArguments( 53 | struct CommandLineParserSpecification* clps, 54 | int32_t argc, const char* const* argv, 55 | const char** other_string_array, uint32_t other_string_array_size); 56 | 57 | #ifdef __cplusplus 58 | } 59 | #endif 60 | 61 | #endif /* COMMAND_LINE_PARSER_H_INCLDED */ 62 | -------------------------------------------------------------------------------- /libs/command_line_parser/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${LIB_NAME} 2 | PRIVATE 3 | ${CMAKE_CURRENT_SOURCE_DIR}/command_line_parser.c 4 | ) 5 | -------------------------------------------------------------------------------- /libs/fft/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | # プロジェクト名 4 | project(FFT C) 5 | 6 | # ライブラリ名 7 | set(LIB_NAME fft) 8 | 9 | # 静的ライブラリ指定 10 | add_library(${LIB_NAME} STATIC) 11 | 12 | # ソースディレクトリ 13 | add_subdirectory(src) 14 | 15 | # インクルードパス 16 | target_include_directories(${LIB_NAME} 17 | PUBLIC 18 | ${CMAKE_CURRENT_SOURCE_DIR}/include 19 | ) 20 | 21 | # コンパイルオプション 22 | if(MSVC) 23 | target_compile_options(${LIB_NAME} PRIVATE /W4) 24 | set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /D DEBUG") 25 | set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /D NDEBUG") 26 | else() 27 | target_compile_options(${LIB_NAME} PRIVATE -Wall -Wextra -Wpedantic -Wformat=2 -Wstrict-aliasing=2 -Wconversion -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition) 28 | set(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -DDEBUG") 29 | set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") 30 | endif() 31 | set_target_properties(${LIB_NAME} 32 | PROPERTIES 33 | C_STANDARD 90 C_EXTENSIONS OFF 34 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 35 | ) 36 | -------------------------------------------------------------------------------- /libs/fft/include/fft.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file fft.h 3 | * @brief FFT(Fast Fourior Transform, 高速フーリエ変換)ライブラリ 4 | */ 5 | #ifndef FFT_H_INCLUDED 6 | #define FFT_H_INCLUDED 7 | 8 | /*! @brief i番目の複素数の実数部にアクセス */ 9 | #define FFTCOMPLEX_REAL(flt_array, i) ((flt_array)[((i) << 1)]) 10 | /*! @brief i番目の複素数の虚数部にアクセス */ 11 | #define FFTCOMPLEX_IMAG(flt_array, i) ((flt_array)[((i) << 1) + 1]) 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | /*! 18 | * @brief FFT(高速フーリエ変換) 19 | * @param[in] n FFT点数 20 | * @param[in] flag -1:FFT, 1:IFFT 21 | * @param[in,out] x フーリエ変換する系列(入出力 2nサイズ必須, 偶数番目に実数部, 奇数番目に虚数部) 22 | * @param[in,out] y 作業用配列(xと同一サイズ) 23 | * @note 正規化は行いません 24 | */ 25 | void FFT_FloatFFT(int n, int flag, double *x, double *y); 26 | 27 | /*! 28 | * @brief 実数配列のFFT(高速フーリエ変換) 29 | * @param[in] n FFT点数 30 | * @param[in] flag -1:FFT, 1:IFFT 31 | * @param[in,out] x フーリエ変換する系列(入出力 nサイズ必須, FFTの場合, x[0]に直流成分の実部, x[1]に最高周波数成分の虚数部が入る) 32 | * @param[in,out] y 作業用配列(xと同一サイズ) 33 | * @note 正規化は行いません。正規化定数は2/nです 34 | */ 35 | void FFT_RealFFT(int n, int flag, double *x, double *y); 36 | 37 | #ifdef __cplusplus 38 | } 39 | #endif 40 | 41 | #endif /* FFT_H_INCLUDED */ 42 | -------------------------------------------------------------------------------- /libs/fft/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${LIB_NAME} 2 | PRIVATE 3 | ${CMAKE_CURRENT_SOURCE_DIR}/fft.c 4 | ) 5 | -------------------------------------------------------------------------------- /libs/fft/src/fft.c: -------------------------------------------------------------------------------- 1 | #include "fft.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | /* インラインキーワードを定義 */ 8 | #if defined(_MSC_VER) 9 | #define FFT_INLINE inline 10 | #elif defined(__GNUC__) 11 | #define FFT_INLINE __inline__ 12 | #else 13 | #define FFT_INLINE 14 | #endif 15 | 16 | /* 円周率 */ 17 | #define FFT_PI 3.14159265358979323846 18 | 19 | /* 複素数型 */ 20 | typedef struct FFTComplex { 21 | double real; /* 実部 */ 22 | double imag; /* 虚部 */ 23 | } FFTComplex; 24 | 25 | /* FFT 正規化は行いません 26 | * n 系列長 27 | * flag -1:FFT, 1:IFFT 28 | * x フーリエ変換する系列(入出力) 29 | * y 作業用配列(xと同一サイズ) 30 | */ 31 | static void FFT_ComplexFFT(int n, int flag, FFTComplex *x, FFTComplex *y); 32 | 33 | /* 複素数型のサイズチェック doubleの配列を複素数型とみなして計算するため 34 | * 構造体にパディングなどが入ってしまうとサイズが合わなくなる 35 | * 合わない場合は#pragmaで構造体をパックする */ 36 | extern char FFT_checksize[(sizeof(FFTComplex) == (sizeof(double) * 2)) ? 1 : -1]; 37 | 38 | /* 複素数加算 */ 39 | static FFT_INLINE FFTComplex FFTComplex_Add(FFTComplex a, FFTComplex b) 40 | { 41 | FFTComplex ret; 42 | ret.real = a.real + b.real; 43 | ret.imag = a.imag + b.imag; 44 | return ret; 45 | } 46 | 47 | /* 複素数減算 */ 48 | static FFT_INLINE FFTComplex FFTComplex_Sub(FFTComplex a, FFTComplex b) 49 | { 50 | FFTComplex ret; 51 | ret.real = a.real - b.real; 52 | ret.imag = a.imag - b.imag; 53 | return ret; 54 | } 55 | 56 | /* 複素数乗算 */ 57 | static FFT_INLINE FFTComplex FFTComplex_Mul(FFTComplex a, FFTComplex b) 58 | { 59 | FFTComplex ret; 60 | ret.real = a.real * b.real - a.imag * b.imag; 61 | ret.imag = a.real * b.imag + a.imag * b.real; 62 | return ret; 63 | } 64 | 65 | /* FFT 正規化は行いません 66 | * n 系列長 67 | * flag -1:FFT, 1:IFFT 68 | * x フーリエ変換する系列(入出力) 69 | * y 作業用配列(xと同一サイズ) 70 | */ 71 | static void FFT_ComplexFFT(int n, const int flag, FFTComplex *x, FFTComplex *y) 72 | { 73 | FFTComplex *tmp, *src = x; 74 | int p, q; 75 | int s = 1; /* ストライド */ 76 | 77 | /* 4基底 Stockham FFT */ 78 | while (n > 2) { 79 | const int n1 = (n >> 2); 80 | const int n2 = (n >> 1); 81 | const int n3 = n1 + n2; 82 | const double theta0 = 2.0 * FFT_PI / n; 83 | FFTComplex j, wdelta, w1p; 84 | j.real = 0.0; j.imag = -flag; 85 | wdelta.real = cos(theta0); wdelta.imag = flag * sin(theta0); 86 | w1p.real = 1.0; w1p.imag = 0.0; 87 | for (p = 0; p < n1; p++) { 88 | /* より精密 しかしsin,cosの関数呼び出しがある 89 | * const FFTComplex w1p = { cos(p * theta0), flag * sin(p * theta0) }; */ 90 | const FFTComplex w2p = FFTComplex_Mul(w1p, w1p); 91 | const FFTComplex w3p = FFTComplex_Mul(w1p, w2p); 92 | for (q = 0; q < s; q++) { 93 | const FFTComplex a = x[q + s * (p + 0)]; 94 | const FFTComplex b = x[q + s * (p + n1)]; 95 | const FFTComplex c = x[q + s * (p + n2)]; 96 | const FFTComplex d = x[q + s * (p + n3)]; 97 | const FFTComplex apc = FFTComplex_Add(a, c); 98 | const FFTComplex amc = FFTComplex_Sub(a, c); 99 | const FFTComplex bpd = FFTComplex_Add(b, d); 100 | const FFTComplex jbmd = FFTComplex_Mul(j, FFTComplex_Sub(b, d)); 101 | y[q + s * ((p << 2) + 0)] = FFTComplex_Add(apc, bpd); 102 | y[q + s * ((p << 2) + 1)] = FFTComplex_Mul(w1p, FFTComplex_Sub(amc, jbmd)); 103 | y[q + s * ((p << 2) + 2)] = FFTComplex_Mul(w2p, FFTComplex_Sub(apc, bpd)); 104 | y[q + s * ((p << 2) + 3)] = FFTComplex_Mul(w3p, FFTComplex_Add(amc, jbmd)); 105 | } 106 | /* 回転係数を進める */ 107 | w1p = FFTComplex_Mul(w1p, wdelta); 108 | } 109 | n >>= 2; 110 | s <<= 2; 111 | tmp = x; x = y; y = tmp; 112 | } 113 | 114 | if (n == 2) { 115 | for (q = 0; q < s; q++) { 116 | const FFTComplex a = x[q + 0]; 117 | const FFTComplex b = x[q + s]; 118 | y[q + 0] = FFTComplex_Add(a, b); 119 | y[q + s] = FFTComplex_Sub(a, b); 120 | } 121 | s <<= 1; 122 | tmp = x; x = y; y = tmp; 123 | } 124 | 125 | if (src != x) { 126 | memcpy(y, x, sizeof(FFTComplex) * (size_t)s); 127 | } 128 | } 129 | 130 | /* FFT 正規化は行いません 131 | * n 系列長 132 | * flag -1:FFT, 1:IFFT 133 | * x フーリエ変換する系列(入出力 2nサイズ必須, 偶数番目に実数部, 奇数番目に虚数部) 134 | * y 作業用配列(xと同一サイズ) 135 | */ 136 | void FFT_FloatFFT(int n, const int flag, double *x, double *y) 137 | { 138 | FFT_ComplexFFT(n, flag, (FFTComplex *)x, (FFTComplex *)y); 139 | } 140 | 141 | /* 実数列のFFT 正規化は行いません 正規化定数は2/n 142 | * n 系列長 143 | * flag -1:FFT, 1:IFFT 144 | * x フーリエ変換する系列(入出力 nサイズ必須, FFTの場合, x[0]に直流成分の実部, x[1]に最高周波数成分の虚数部が入る) 145 | * y 作業用配列(xと同一サイズ) 146 | */ 147 | void FFT_RealFFT(int n, const int flag, double *x, double *y) 148 | { 149 | int i; 150 | const double theta = flag * 2.0 * FFT_PI / n; 151 | const double wpi = sin(theta); 152 | const double wpr = cos(theta) - 1.0; 153 | const double c2 = flag * 0.5; 154 | double wr, wi, wtmp; 155 | 156 | /* FFTの場合は先に変換 */ 157 | if (flag == -1) { 158 | FFT_FloatFFT(n >> 1, -1, x, y); 159 | } 160 | 161 | /* 回転因子初期化 */ 162 | wr = 1.0 + wpr; 163 | wi = wpi; 164 | 165 | /* スペクトルの対称性を使用し */ 166 | /* FFTの場合は最終結果をまとめ、IFFTの場合は元に戻るよう整理 */ 167 | for (i = 1; i <= (n >> 2); i++) { 168 | const int i1 = (i << 1); 169 | const int i2 = i1 + 1; 170 | const int i3 = n - i1; 171 | const int i4 = i3 + 1; 172 | const double h1r = 0.5 * (x[i1] + x[i3]); 173 | const double h1i = 0.5 * (x[i2] - x[i4]); 174 | const double h2r = -c2 * (x[i2] + x[i4]); 175 | const double h2i = c2 * (x[i1] - x[i3]); 176 | x[i1] = h1r + (wr * h2r) - (wi * h2i); 177 | x[i2] = h1i + (wr * h2i) + (wi * h2r); 178 | x[i3] = h1r - (wr * h2r) + (wi * h2i); 179 | x[i4] = -h1i + (wr * h2i) + (wi * h2r); 180 | /* 回転因子更新 */ 181 | wtmp = wr; 182 | wr += wtmp * wpr - wi * wpi; 183 | wi += wi * wpr + wtmp * wpi; 184 | } 185 | 186 | /* 直流成分/最高周波数成分 */ 187 | { 188 | const double h1r = x[0]; 189 | if (flag == -1) { 190 | x[0] = h1r + x[1]; 191 | x[1] = h1r - x[1]; 192 | } else { 193 | x[0] = 0.5 * (h1r + x[1]); 194 | x[1] = 0.5 * (h1r - x[1]); 195 | FFT_FloatFFT(n >> 1, 1, x, y); 196 | } 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /libs/lpc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # プロジェクト名 6 | project(LPC C) 7 | 8 | # ライブラリ名 9 | set(LIB_NAME lpc) 10 | 11 | # 静的ライブラリ指定 12 | add_library(${LIB_NAME} STATIC) 13 | 14 | # ソースディレクトリ 15 | add_subdirectory(src) 16 | 17 | # インクルードパス 18 | target_include_directories(${LIB_NAME} 19 | PRIVATE 20 | ${PROJECT_ROOT_PATH}/include 21 | ${PROJECT_ROOT_PATH}/libs/fft/include 22 | PUBLIC 23 | ${CMAKE_CURRENT_SOURCE_DIR}/include 24 | ) 25 | 26 | # コンパイルオプション 27 | if(MSVC) 28 | target_compile_options(${LIB_NAME} PRIVATE /W4) 29 | else() 30 | target_compile_options(${LIB_NAME} PRIVATE -Wall -Wextra -Wpedantic -Wformat=2 -Wstrict-aliasing=2 -Wconversion -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition) 31 | set(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -DDEBUG") 32 | set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") 33 | endif() 34 | set_target_properties(${LIB_NAME} 35 | PROPERTIES 36 | C_STANDARD 90 C_EXTENSIONS OFF 37 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 38 | ) 39 | -------------------------------------------------------------------------------- /libs/lpc/include/lpc.h: -------------------------------------------------------------------------------- 1 | #ifndef LPC_H_INCLUDED 2 | #define LPC_H_INCLUDED 3 | 4 | #include 5 | 6 | /* API結果型 */ 7 | typedef enum LPCApiResultTag { 8 | LPC_APIRESULT_OK = 0, /* OK */ 9 | LPC_APIRESULT_NG, /* 分類不能なエラー */ 10 | LPC_APIRESULT_INVALID_ARGUMENT, /* 不正な引数 */ 11 | LPC_APIRESULT_EXCEED_MAX_ORDER, /* 最大次数を超えた */ 12 | LPC_APIRESULT_EXCEED_MAX_NUM_SAMPLES, /* 最大入力サンプル数を超えた */ 13 | LPC_APIRESULT_FAILED_TO_CALCULATION /* 計算に失敗 */ 14 | } LPCApiResult; 15 | 16 | /* 窓関数の種類 */ 17 | typedef enum LPCWindowTypeTag { 18 | LPC_WINDOWTYPE_RECTANGULAR = 0, /* 矩形窓 */ 19 | LPC_WINDOWTYPE_SIN, /* サイン窓 */ 20 | LPC_WINDOWTYPE_WELCH /* Welch窓 */ 21 | } LPCWindowType; 22 | 23 | /* LPC係数計算ハンドル */ 24 | struct LPCCalculator; 25 | 26 | /* 初期化コンフィグ */ 27 | struct LPCCalculatorConfig { 28 | uint32_t max_order; /* 最大次数 */ 29 | uint32_t max_num_samples; /* 最大入力サンプル数 */ 30 | }; 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | /* LPC係数計算ハンドルのワークサイズ計算 */ 37 | int32_t LPCCalculator_CalculateWorkSize(const struct LPCCalculatorConfig *config); 38 | 39 | /* LPC係数計算ハンドルの作成 */ 40 | struct LPCCalculator *LPCCalculator_Create(const struct LPCCalculatorConfig *config, void *work, int32_t work_size); 41 | 42 | /* LPC係数計算ハンドルの破棄 */ 43 | void LPCCalculator_Destroy(struct LPCCalculator *lpcc); 44 | 45 | /* Levinson-Durbin再帰計算によりLPC係数を求める */ 46 | LPCApiResult LPCCalculator_CalculateLPCCoefficients( 47 | struct LPCCalculator *lpcc, 48 | const double *data, uint32_t num_samples, double *coef, uint32_t coef_order, 49 | LPCWindowType window_type, double regular_term); 50 | 51 | /* Levinson-Durbin再帰計算により与えられた次数まで全てのLPC係数を求める(倍精度) */ 52 | /* error_varsは0次の誤差分散(分散)からmax_coef_order次の分散まで求めるためerror_varsのサイズはmax_coef_order+1要する */ 53 | LPCApiResult LPCCalculator_CalculateMultipleLPCCoefficients( 54 | struct LPCCalculator* lpcc, 55 | const double* data, uint32_t num_samples, double **lpc_coefs, double *error_vars, uint32_t max_coef_order, 56 | LPCWindowType window_type, double regular_term); 57 | 58 | /* 補助関数法よりLPC係数を求める(倍精度) */ 59 | LPCApiResult LPCCalculator_CalculateLPCCoefficientsAF( 60 | struct LPCCalculator *lpcc, 61 | const double *data, uint32_t num_samples, double *coef, uint32_t coef_order, 62 | uint32_t max_num_iteration, LPCWindowType window_type, double regular_term); 63 | 64 | /* Burg法によりLPC係数を求める(倍精度) */ 65 | LPCApiResult LPCCalculator_CalculateLPCCoefficientsBurg( 66 | struct LPCCalculator *lpcc, 67 | const double *data, uint32_t num_samples, double *coef, uint32_t coef_order); 68 | 69 | /* SVRよりLPC係数を求める(倍精度) */ 70 | LPCApiResult LPCCalculator_CalculateLPCCoefficientsSVR( 71 | struct LPCCalculator *lpcc, 72 | const double *data, uint32_t num_samples, double *coef, uint32_t coef_order, 73 | uint32_t max_num_iteration, LPCWindowType window_type, 74 | double regular_term, const double *margin_list, uint32_t margin_list_size); 75 | 76 | /* 入力データからサンプルあたりの推定符号長を求める */ 77 | LPCApiResult LPCCalculator_EstimateCodeLength( 78 | struct LPCCalculator *lpcc, 79 | const double *data, uint32_t num_samples, uint32_t bits_per_sample, 80 | uint32_t coef_order, double *length_per_sample_bits, LPCWindowType window_type); 81 | 82 | /* MDL(最小記述長)を計算 */ 83 | LPCApiResult LPCCalculator_CalculateMDL( 84 | struct LPCCalculator *lpcc, 85 | const double *data, uint32_t num_samples, uint32_t coef_order, double *mdl, 86 | LPCWindowType window_type); 87 | 88 | /* LPC係数をPARCOR係数に変換して量子化する */ 89 | LPCApiResult LPC_QuantizeCoefficientsAsPARCOR( 90 | struct LPCCalculator *lpcc, 91 | const double *lpc_coef, uint32_t coef_order, uint32_t nbits_precision, int32_t *int_coef); 92 | 93 | /* LPC係数の整数量子化 */ 94 | LPCApiResult LPC_QuantizeCoefficients( 95 | const double *double_coef, uint32_t coef_order, uint32_t nbits_precision, uint32_t max_bits, 96 | int32_t *int_coef, uint32_t *coef_rshift); 97 | 98 | /* LPC係数により予測/誤差出力 */ 99 | LPCApiResult LPC_Predict( 100 | const int32_t *data, uint32_t num_samples, 101 | const int32_t *coef, uint32_t coef_order, int32_t *residual, uint32_t coef_rshift); 102 | 103 | /* LPC係数により合成(in-place) */ 104 | LPCApiResult LPC_Synthesize( 105 | int32_t *data, uint32_t num_samples, 106 | const int32_t *coef, uint32_t coef_order, uint32_t coef_rshift); 107 | 108 | #ifdef __cplusplus 109 | } 110 | #endif 111 | 112 | #endif /* LPC_H_INCLUDED */ 113 | -------------------------------------------------------------------------------- /libs/lpc/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${LIB_NAME} 2 | PRIVATE 3 | ${CMAKE_CURRENT_SOURCE_DIR}/lpc.c 4 | ) 5 | -------------------------------------------------------------------------------- /libs/srla_coder/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # プロジェクト名 6 | project(SRLACoder C) 7 | 8 | # ライブラリ名 9 | set(LIB_NAME srla_coder) 10 | 11 | # 静的ライブラリ指定 12 | add_library(${LIB_NAME} STATIC) 13 | 14 | # ソースディレクトリ 15 | add_subdirectory(src) 16 | 17 | # インクルードパス 18 | target_include_directories(${LIB_NAME} 19 | PRIVATE 20 | ${PROJECT_ROOT_PATH}/include 21 | ${PROJECT_ROOT_PATH}/libs/bit_stream/include 22 | ${PROJECT_ROOT_PATH}/libs/static_huffman/include 23 | ${PROJECT_ROOT_PATH}/libs/srla_internal/include 24 | PUBLIC 25 | ${CMAKE_CURRENT_SOURCE_DIR}/include 26 | ) 27 | 28 | # コンパイルオプション 29 | if(MSVC) 30 | target_compile_options(${LIB_NAME} PRIVATE /W4) 31 | else() 32 | target_compile_options(${LIB_NAME} PRIVATE -Wall -Wextra -Wpedantic -Wformat=2 -Wstrict-aliasing=2 -Wconversion -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition) 33 | set(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -DDEBUG") 34 | set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") 35 | endif() 36 | set_target_properties(${LIB_NAME} 37 | PROPERTIES 38 | C_STANDARD 90 C_EXTENSIONS OFF 39 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 40 | ) 41 | -------------------------------------------------------------------------------- /libs/srla_coder/include/srla_coder.h: -------------------------------------------------------------------------------- 1 | #ifndef SRLACODER_H_INCLUDED 2 | #define SRLACODER_H_INCLUDED 3 | 4 | #include 5 | #include "bit_stream.h" 6 | 7 | /* 符号化ハンドル */ 8 | struct SRLACoder; 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /* 符号化ハンドルの作成に必要なワークサイズの計算 */ 15 | int32_t SRLACoder_CalculateWorkSize(uint32_t max_num_samples); 16 | 17 | /* 符号化ハンドルの作成 */ 18 | struct SRLACoder* SRLACoder_Create(uint32_t max_num_samples, void *work, int32_t work_size); 19 | 20 | /* 符号化ハンドルの破棄 */ 21 | void SRLACoder_Destroy(struct SRLACoder *coder); 22 | 23 | /* 符号長計算 */ 24 | uint32_t SRLACoder_ComputeCodeLength(struct SRLACoder *coder, const int32_t *data, uint32_t num_samples); 25 | 26 | /* 符号付き整数配列の符号化 */ 27 | void SRLACoder_Encode(struct SRLACoder *coder, struct BitStream *stream, const int32_t *data, uint32_t num_samples); 28 | 29 | /* 符号付き整数配列の復号 */ 30 | void SRLACoder_Decode(struct BitStream *stream, int32_t *data, uint32_t num_samples); 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | 36 | #endif /* SRLACODER_H_INCLUDED */ 37 | -------------------------------------------------------------------------------- /libs/srla_coder/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${LIB_NAME} 2 | PRIVATE 3 | ${CMAKE_CURRENT_SOURCE_DIR}/srla_coder.c 4 | ) 5 | -------------------------------------------------------------------------------- /libs/srla_decoder/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # プロジェクト名 6 | project(SRLADecoder C) 7 | 8 | # ライブラリ名 9 | set(LIB_NAME srla_decoder) 10 | 11 | # 静的ライブラリ指定 12 | add_library(${LIB_NAME} STATIC) 13 | 14 | # ソースディレクトリ 15 | add_subdirectory(src) 16 | 17 | # インクルードパス 18 | target_include_directories(${LIB_NAME} 19 | PRIVATE 20 | ${PROJECT_ROOT_PATH}/include 21 | ${PROJECT_ROOT_PATH}/libs/byte_array/include 22 | ${PROJECT_ROOT_PATH}/libs/bit_stream/include 23 | ${PROJECT_ROOT_PATH}/libs/static_huffman/include 24 | ${PROJECT_ROOT_PATH}/libs/lpc/include 25 | ${PROJECT_ROOT_PATH}/libs/srla_internal/include 26 | ${PROJECT_ROOT_PATH}/libs/srla_coder/include 27 | PUBLIC 28 | ${CMAKE_CURRENT_SOURCE_DIR}/include 29 | ) 30 | 31 | # コンパイルオプション 32 | if(MSVC) 33 | target_compile_options(${LIB_NAME} PRIVATE /W4) 34 | else() 35 | target_compile_options(${LIB_NAME} PRIVATE -Wall -Wextra -Wpedantic -Wformat=2 -Wstrict-aliasing=2 -Wconversion -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition) 36 | set(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -DDEBUG") 37 | set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") 38 | endif() 39 | set_target_properties(${LIB_NAME} 40 | PROPERTIES 41 | C_STANDARD 90 C_EXTENSIONS OFF 42 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 43 | ) 44 | -------------------------------------------------------------------------------- /libs/srla_decoder/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${LIB_NAME} 2 | PRIVATE 3 | ${CMAKE_CURRENT_SOURCE_DIR}/srla_decoder.c 4 | ${CMAKE_CURRENT_SOURCE_DIR}/srla_lpc_synthesize.c 5 | ${CMAKE_CURRENT_SOURCE_DIR}/srla_lpc_synthesize.h 6 | ) 7 | -------------------------------------------------------------------------------- /libs/srla_decoder/src/srla_lpc_synthesize.h: -------------------------------------------------------------------------------- 1 | #ifndef SRLA_LPCSYNTHESIZE_H_INCLUDED 2 | #define SRLA_LPCSYNTHESIZE_H_INCLUDED 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /* LPC係数により合成(in-place) */ 11 | void SRLALPC_Synthesize( 12 | int32_t *data, uint32_t num_samples, const int32_t *coef, uint32_t coef_order, uint32_t coef_rshift); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif /* SRLA_LPCSYNTHESIZE_H_INCLUDED */ 19 | -------------------------------------------------------------------------------- /libs/srla_encoder/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # プロジェクト名 6 | project(SRLAEncoder C) 7 | 8 | # ライブラリ名 9 | set(LIB_NAME srla_encoder) 10 | 11 | # 静的ライブラリ指定 12 | add_library(${LIB_NAME} STATIC) 13 | 14 | # ソースディレクトリ 15 | add_subdirectory(src) 16 | 17 | # インクルードパス 18 | target_include_directories(${LIB_NAME} 19 | PRIVATE 20 | ${PROJECT_ROOT_PATH}/include 21 | ${PROJECT_ROOT_PATH}/libs/byte_array/include 22 | ${PROJECT_ROOT_PATH}/libs/bit_stream/include 23 | ${PROJECT_ROOT_PATH}/libs/static_huffman/include 24 | ${PROJECT_ROOT_PATH}/libs/lpc/include 25 | ${PROJECT_ROOT_PATH}/libs/srla_internal/include 26 | ${PROJECT_ROOT_PATH}/libs/srla_coder/include 27 | PUBLIC 28 | ${CMAKE_CURRENT_SOURCE_DIR}/include 29 | ) 30 | 31 | # コンパイルオプション 32 | if(MSVC) 33 | target_compile_options(${LIB_NAME} PRIVATE /W4) 34 | else() 35 | target_compile_options(${LIB_NAME} PRIVATE -Wall -Wextra -Wpedantic -Wformat=2 -Wstrict-aliasing=2 -Wconversion -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition) 36 | set(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -DDEBUG") 37 | set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") 38 | endif() 39 | set_target_properties(${LIB_NAME} 40 | PROPERTIES 41 | C_STANDARD 90 C_EXTENSIONS OFF 42 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 43 | ) 44 | -------------------------------------------------------------------------------- /libs/srla_encoder/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${LIB_NAME} 2 | PRIVATE 3 | ${CMAKE_CURRENT_SOURCE_DIR}/srla_encoder.c 4 | ${CMAKE_CURRENT_SOURCE_DIR}/srla_lpc_predict.c 5 | ${CMAKE_CURRENT_SOURCE_DIR}/srla_lpc_predict.h 6 | ) 7 | -------------------------------------------------------------------------------- /libs/srla_encoder/src/srla_lpc_predict.h: -------------------------------------------------------------------------------- 1 | #ifndef SRLA_LPCPREDICTOR_H_INCLUDED 2 | #define SRLA_LPCPREDICTOR_H_INCLUDED 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /* LPC係数により予測/誤差出力 */ 11 | void SRLALPC_Predict( 12 | const int32_t *data, uint32_t num_samples, 13 | const int32_t *coef, uint32_t coef_order, int32_t *residual, uint32_t coef_rshift); 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif /* SRLA_LPCPREDICTOR_H_INCLUDED */ 20 | -------------------------------------------------------------------------------- /libs/srla_internal/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # プロジェクト名 6 | project(SRLAInternal C) 7 | 8 | # ライブラリ名 9 | set(LIB_NAME srla_internal) 10 | 11 | # 静的ライブラリ指定 12 | add_library(${LIB_NAME} STATIC) 13 | 14 | # ソースディレクトリ 15 | add_subdirectory(src) 16 | 17 | # インクルードパス 18 | target_include_directories(${LIB_NAME} 19 | PRIVATE 20 | ${PROJECT_ROOT_PATH}/include 21 | ${PROJECT_ROOT_PATH}/libs/bit_stream/include 22 | ${PROJECT_ROOT_PATH}/libs/static_huffman/include 23 | PUBLIC 24 | ${CMAKE_CURRENT_SOURCE_DIR}/include 25 | ) 26 | 27 | # コンパイルオプション 28 | if(MSVC) 29 | target_compile_options(${LIB_NAME} PRIVATE /W4) 30 | else() 31 | target_compile_options(${LIB_NAME} PRIVATE -Wall -Wextra -Wpedantic -Wformat=2 -Wstrict-aliasing=2 -Wconversion -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition) 32 | set(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -DDEBUG") 33 | set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") 34 | endif() 35 | set_target_properties(${LIB_NAME} 36 | PROPERTIES 37 | C_STANDARD 90 C_EXTENSIONS OFF 38 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 39 | ) 40 | -------------------------------------------------------------------------------- /libs/srla_internal/include/srla_internal.h: -------------------------------------------------------------------------------- 1 | #ifndef SRLA_INTERNAL_H_INCLUDED 2 | #define SRLA_INTERNAL_H_INCLUDED 3 | 4 | #include "srla.h" 5 | #include "srla_stdint.h" 6 | #include "static_huffman.h" 7 | 8 | /* 本ライブラリのメモリアラインメント */ 9 | #define SRLA_MEMORY_ALIGNMENT 16 10 | /* ブロック先頭の同期コード */ 11 | #define SRLA_BLOCK_SYNC_CODE 0xFFFF 12 | 13 | /* 内部エンコードパラメータ */ 14 | /* プリエンファシスの係数シフト量 */ 15 | #define SRLA_PREEMPHASIS_COEF_SHIFT 4 16 | /* プリエンファシスフィルタの適用回数 */ 17 | #define SRLA_NUM_PREEMPHASIS_FILTERS 2 18 | /* LPC係数のビット幅 */ 19 | #define SRLA_LPC_COEFFICIENT_BITWIDTH 8 20 | /* LPC係数右シフト量のビット幅 */ 21 | #define SRLA_RSHIFT_LPC_COEFFICIENT_BITWIDTH 4 22 | /* (LPC係数次数-1)のビット幅 */ 23 | #define SRLA_LPC_COEFFICIENT_ORDER_BITWIDTH 8 24 | /* LPCのリッジ正則化パラメータ */ 25 | #define SRLA_LPC_RIDGE_REGULARIZATION_PARAMETER 1e-5 26 | 27 | /* アサートマクロ */ 28 | #ifdef NDEBUG 29 | /* 未使用変数警告を明示的に回避 */ 30 | #define SRLA_ASSERT(condition) ((void)(condition)) 31 | #else 32 | #include 33 | #define SRLA_ASSERT(condition) assert(condition) 34 | #endif 35 | 36 | /* 静的アサートマクロ */ 37 | #define SRLA_STATIC_ASSERT(expr) extern void assertion_failed(char dummy[(expr) ? 1 : -1]) 38 | 39 | /* ブロックデータタイプ */ 40 | typedef enum SRLABlockDataTypeTag { 41 | SRLA_BLOCK_DATA_TYPE_COMPRESSDATA = 0, /* 圧縮済みデータ */ 42 | SRLA_BLOCK_DATA_TYPE_SILENT = 1, /* 無音データ */ 43 | SRLA_BLOCK_DATA_TYPE_RAWDATA = 2, /* 生データ */ 44 | SRLA_BLOCK_DATA_TYPE_INVALID = 3 /* 無効 */ 45 | } SRLABlockDataType; 46 | 47 | /* マルチチャンネル処理の決定方法 */ 48 | typedef enum SRLAChannelProcessMethodTacticsTag { 49 | SRLA_CH_PROCESS_METHOD_TACTICS_NONE = 0, /* 何もしない */ 50 | SRLA_CH_PROCESS_METHOD_TACTICS_MS_FIXED, /* ステレオMS処理を常に選択 */ 51 | SRLA_CH_PROCESS_METHOD_TACTICS_ADAPTIVE, /* 適応的にLR,LS,RS,MSを選択 */ 52 | SRLA_CH_PROCESS_METHOD_TACTICS_INVALID /* 無効値 */ 53 | } SRLAChannelProcessMethodTactics; 54 | 55 | /* マルチチャンネル処理法 */ 56 | typedef enum SRLAChannelProcessMethodTag { 57 | SRLA_CH_PROCESS_METHOD_NONE = 0, /* 何もしない */ 58 | SRLA_CH_PROCESS_METHOD_MS = 1, /* ステレオMS処理 */ 59 | SRLA_CH_PROCESS_METHOD_LS = 2, /* ステレオLS処理 */ 60 | SRLA_CH_PROCESS_METHOD_SR = 3, /* ステレオSR処理 */ 61 | SRLA_CH_PROCESS_METHOD_INVALID /* 無効値 */ 62 | } SRLAChannelProcessMethod; 63 | 64 | /* LPCの次数決定方法 */ 65 | typedef enum SRLAChannelLPCOrderDecisionTacticsTag { 66 | SRLA_LPC_ORDER_DECISION_TACTICS_MAX_FIXED = 0, /* 最大次数を常に選択 */ 67 | SRLA_LPC_ORDER_DECISION_TACTICS_BRUTEFORCE_SEARCH, /* 素朴な網羅探索 */ 68 | SRLA_LPC_ORDER_DECISION_TACTICS_BRUTEFORCE_ESTIMATION, /* 残差分散の推定による網羅探索 */ 69 | SRLA_LPC_ORDER_DECISION_TACTICS_INVALID /* 無効値 */ 70 | } SRLAChannelLPCOrderDecisionTactics; 71 | 72 | /* 内部エラー型 */ 73 | typedef enum SRLAErrorTag { 74 | SRLA_ERROR_OK = 0, /* OK */ 75 | SRLA_ERROR_NG, /* 分類不能な失敗 */ 76 | SRLA_ERROR_INVALID_ARGUMENT, /* 不正な引数 */ 77 | SRLA_ERROR_INVALID_FORMAT, /* 不正なフォーマット */ 78 | SRLA_ERROR_INSUFFICIENT_BUFFER, /* バッファサイズが足りない */ 79 | SRLA_ERROR_INSUFFICIENT_DATA /* データサイズが足りない */ 80 | } SRLAError; 81 | 82 | /* パラメータプリセット */ 83 | struct SRLAParameterPreset { 84 | uint32_t max_num_parameters; /* 最大パラメータ数 */ 85 | SRLAChannelProcessMethodTactics ch_process_method_tactics; /* マルチチャンネル処理の決定法 */ 86 | SRLAChannelLPCOrderDecisionTactics lpc_order_tactics; /* LPCの次数決定法 */ 87 | uint32_t svr_max_num_iterations; /* SVRの最大繰り返し回数 */ 88 | const double *margin_list; /* マージンリスト */ 89 | uint32_t margin_list_size; /* マージンリストサイズ */ 90 | }; 91 | 92 | #ifdef __cplusplus 93 | extern "C" { 94 | #endif 95 | 96 | /* パラメータプリセット配列 */ 97 | extern const struct SRLAParameterPreset g_srla_parameter_preset[]; 98 | 99 | /* パラメータ符号用のハフマン木を取得 */ 100 | const struct StaticHuffmanTree* SRLA_GetParameterHuffmanTree(void); 101 | 102 | /* 和をとったパラメータ符号用のハフマン木を取得 */ 103 | const struct StaticHuffmanTree *SRLA_GetSumParameterHuffmanTree(void); 104 | 105 | 106 | #ifdef __cplusplus 107 | } 108 | #endif 109 | 110 | #endif /* SRLA_INTERNAL_H_INCLUDED */ 111 | -------------------------------------------------------------------------------- /libs/srla_internal/include/srla_utility.h: -------------------------------------------------------------------------------- 1 | #ifndef SRLAUTILITY_H_INCLUDED 2 | #define SRLAUTILITY_H_INCLUDED 3 | 4 | #include "srla_stdint.h" 5 | #include 6 | 7 | /* 未使用引数警告回避 */ 8 | #define SRLAUTILITY_UNUSED_ARGUMENT(arg) ((void)(arg)) 9 | /* 算術右シフト */ 10 | #if ((((int32_t)-1) >> 1) == ((int32_t)-1)) 11 | /* 算術右シフトが有効な環境では、そのまま右シフト */ 12 | #define SRLAUTILITY_SHIFT_RIGHT_ARITHMETIC(sint32, rshift) ((sint32) >> (rshift)) 13 | #else 14 | /* 算術右シフトが無効な環境では、自分で定義する ハッカーのたのしみのより引用 */ 15 | /* 注意)有効範囲:0 <= rshift <= 32 */ 16 | #define SRLAUTILITY_SHIFT_RIGHT_ARITHMETIC(sint32, rshift) ((((uint64_t)(sint32) + 0x80000000UL) >> (rshift)) - (0x80000000UL >> (rshift))) 17 | #endif 18 | /* 符号関数 ハッカーのたのしみより引用 補足)val==0の時は0を返す */ 19 | #define SRLAUTILITY_SIGN(val) (((val) > 0) - ((val) < 0)) 20 | /* nの倍数への切り上げ */ 21 | #define SRLAUTILITY_ROUNDUP(val, n) ((((val) + ((n) - 1)) / (n)) * (n)) 22 | /* 最大値の取得 */ 23 | #define SRLAUTILITY_MAX(a,b) (((a) > (b)) ? (a) : (b)) 24 | /* 最小値の取得 */ 25 | #define SRLAUTILITY_MIN(a,b) (((a) < (b)) ? (a) : (b)) 26 | /* 最小値以上最小値以下に制限 */ 27 | #define SRLAUTILITY_INNER_VALUE(val, min, max) (SRLAUTILITY_MIN((max), SRLAUTILITY_MAX((min), (val)))) 28 | /* 2の冪乗か? */ 29 | #define SRLAUTILITY_IS_POWERED_OF_2(val) (!((val) & ((val) - 1))) 30 | /* 符号付き32bit数値を符号なし32bit数値に一意変換 */ 31 | #define SRLAUTILITY_SINT32_TO_UINT32(sint) ((uint32_t)((-((sint) < 0)) ^ ((sint) << 1))) 32 | /* 符号なし32bit数値を符号付き32bit数値に一意変換 */ 33 | #define SRLAUTILITY_UINT32_TO_SINT32(uint) ((int32_t)((uint) >> 1) ^ -(int32_t)((uint) & 1)) 34 | /* 絶対値の取得 */ 35 | #define SRLAUTILITY_ABS(val) (((val) > 0) ? (val) : -(val)) 36 | 37 | /* NLZ(最上位ビットから1に当たるまでのビット数)の計算 */ 38 | #if defined(__GNUC__) 39 | /* ビルトイン関数を使用 */ 40 | #define SRLAUTILITY_NLZ(x) (((x) > 0) ? (uint32_t)__builtin_clz(x) : 32U) 41 | #elif defined(_MSC_VER) 42 | #include 43 | /* ビルトイン関数を使用 */ 44 | __inline uint32_t SRLAUTILITY_NLZ(uint32_t x) 45 | { 46 | return __lzcnt(x); 47 | } 48 | #else 49 | /* ソフトウェア実装を使用 */ 50 | #define SRLAUTILITY_NLZ(x) SRLAUtility_NLZSoft(x) 51 | #endif 52 | 53 | /* ceil(log2(val))の計算 */ 54 | #define SRLAUTILITY_LOG2CEIL(x) (32U - SRLAUTILITY_NLZ((uint32_t)((x) - 1U))) 55 | /* floor(log2(val))の計算 */ 56 | #define SRLAUTILITY_LOG2FLOOR(x) (31U - SRLAUTILITY_NLZ(x)) 57 | 58 | /* 2の冪乗数(1,2,4,8,16,...)への切り上げ */ 59 | #if defined(__GNUC__) || defined(_MSC_VER) 60 | /* ビルトイン関数を使用 */ 61 | #define SRLAUTILITY_ROUNDUP2POWERED(x) (1U << SRLAUTILITY_LOG2CEIL(x)) 62 | #else 63 | /* ソフトウェア実装を使用 */ 64 | #define SRLAUTILITY_ROUNDUP2POWERED(x) SRLAUtility_RoundUp2PoweredSoft(x) 65 | #endif 66 | 67 | /* 2次元配列の領域ワークサイズ計算 */ 68 | #define SRLA_CALCULATE_2DIMARRAY_WORKSIZE(type, size1, size2)\ 69 | ((size1) * ((int32_t)sizeof(type *) + SRLA_MEMORY_ALIGNMENT\ 70 | + (size2) * (int32_t)sizeof(type) + SRLA_MEMORY_ALIGNMENT)) 71 | 72 | /* 2次元配列の領域割当て */ 73 | #define SRLA_ALLOCATE_2DIMARRAY(ptr, work_ptr, type, size1, size2)\ 74 | do {\ 75 | uint32_t i;\ 76 | (work_ptr) = (uint8_t *)SRLAUTILITY_ROUNDUP((uintptr_t)work_ptr, SRLA_MEMORY_ALIGNMENT);\ 77 | (ptr) = (type **)work_ptr;\ 78 | (work_ptr) += sizeof(type *) * (size1);\ 79 | for (i = 0; i < (size1); i++) {\ 80 | (work_ptr) = (uint8_t *)SRLAUTILITY_ROUNDUP((uintptr_t)work_ptr, SRLA_MEMORY_ALIGNMENT);\ 81 | (ptr)[i] = (type *)work_ptr;\ 82 | (work_ptr) += sizeof(type) * (size2);\ 83 | }\ 84 | } while (0) 85 | 86 | /* プリエンファシス/デエンファシスフィルタ */ 87 | struct SRLAPreemphasisFilter { 88 | int32_t prev; 89 | int32_t coef; 90 | }; 91 | 92 | #ifdef __cplusplus 93 | extern "C" { 94 | #endif 95 | 96 | /* round関数(C89で用意されていない) */ 97 | double SRLAUtility_Round(double d); 98 | 99 | /* log2関数(C89で定義されていない) */ 100 | double SRLAUtility_Log2(double d); 101 | 102 | /* フレッチャーのチェックサム計算 */ 103 | uint16_t SRLAUtility_CalculateFletcher16CheckSum(const uint8_t *data, size_t data_size); 104 | 105 | /* NLZ(最上位ビットから1に当たるまでのビット数)の計算 */ 106 | uint32_t SRLAUtility_NLZSoft(uint32_t val); 107 | 108 | /* 2の冪乗に切り上げる */ 109 | uint32_t SRLAUtility_RoundUp2PoweredSoft(uint32_t val); 110 | 111 | /* LR -> MS (in-place) */ 112 | void SRLAUtility_LRtoMSConversion(int32_t **buffer, uint32_t num_samples); 113 | 114 | /* MS -> LR (in-place) */ 115 | void SRLAUtility_MStoLRConversion(int32_t **buffer, uint32_t num_samples); 116 | 117 | /* LR -> LS (in-place) */ 118 | void SRLAUtility_LRtoLSConversion(int32_t **buffer, uint32_t num_samples); 119 | 120 | /* LS -> LR (in-place) */ 121 | void SRLAUtility_LStoLRConversion(int32_t **buffer, uint32_t num_samples); 122 | 123 | /* LR -> SR (in-place) */ 124 | void SRLAUtility_LRtoSRConversion(int32_t **buffer, uint32_t num_samples); 125 | 126 | /* SR -> LR (in-place) */ 127 | void SRLAUtility_SRtoLRConversion(int32_t **buffer, uint32_t num_samples); 128 | 129 | /* プリエンファシスフィルタ初期化 */ 130 | void SRLAPreemphasisFilter_Initialize(struct SRLAPreemphasisFilter *preem); 131 | 132 | /* 多段プリエンファシスの係数計算 */ 133 | void SRLAPreemphasisFilter_CalculateMultiStageCoefficients( 134 | struct SRLAPreemphasisFilter *preem, uint32_t num_preem, const int32_t *buffer, uint32_t num_samples); 135 | 136 | /* プリエンファシス */ 137 | void SRLAPreemphasisFilter_Preemphasis( 138 | struct SRLAPreemphasisFilter *preem, int32_t *buffer, uint32_t num_samples); 139 | 140 | /* デエンファシスを複数回適用 */ 141 | void SRLAPreemphasisFilter_MultiStageDeemphasis( 142 | struct SRLAPreemphasisFilter *preem, uint32_t num_preem, int32_t *buffer, uint32_t num_samples); 143 | 144 | #ifdef __cplusplus 145 | } 146 | #endif 147 | 148 | #endif /* SRLAUTILITY_H_INCLUDED */ 149 | -------------------------------------------------------------------------------- /libs/srla_internal/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${LIB_NAME} 2 | PRIVATE 3 | ${CMAKE_CURRENT_SOURCE_DIR}/srla_internal.c 4 | ${CMAKE_CURRENT_SOURCE_DIR}/srla_utility.c 5 | ) 6 | -------------------------------------------------------------------------------- /libs/srla_internal/src/srla_internal.c: -------------------------------------------------------------------------------- 1 | #include "srla_internal.h" 2 | 3 | /* 配列の要素数を取得 */ 4 | #define SRLA_NUM_ARRAY_ELEMENTS(array) ((sizeof(array)) / (sizeof(array[0]))) 5 | /* プリセットの要素定義 */ 6 | #define SRLA_DEFINE_ARRAY_AND_NUM_ELEMTNS_TUPLE(array) array, SRLA_NUM_ARRAY_ELEMENTS(array) 7 | 8 | /* 係数頻度テーブル */ 9 | static const uint32_t st_parameter_frequency_table[256] = { 10 | 76095348,72254718,72258289,63169964,63262546,52582715,52810486,42799643,43131372,34676884,35025512,28243398,28590416,23273860,23593636,19444616,19733938,16446878,16704846,14066952,14313948,12156323,12394627,10604076,10825956,9314730,9540212,8242626,8464666,7332022,7557602,6570127,6797925,5912557,6142141,5354150,5585914,4869738,5094289,4442801,4677350,4061066,4300506,3734416,3970760,3443153,3677752,3189336,3415782,2954645,3178799,2752660,2967304,2569629,2777818,2404070,2602129,2251526,2443398,2115191,2295804,1994923,2161063,1881480,2038816,1782001,1931327,1688512,1828096,1603621,1735000,1523384,1646608,1452862,1563894,1386331,1487586,1320447,1420407,1265884,1355113,1211841,1295332,1161989,1238282,1114927,1186918,1072409,1135479,1034770,1091431,997182,1050869,963398,1008932,933383,973547,902972,939221,877933,907715,851195,876962,825853,848225,804809,818805,783712,792994,765063,767005,750435,745417,734880,722293,721918,700870,710671,678511,697871,659889,688367,640648,679564,620449,670553,603031,875550,610759,1063717,615479,1028599,589957,992095,565814,960957,540335,928279,519599,897352,498592,866879,480292,839276,459937,811359,442661,785004,423731,761996,408680,739625,392501,718562,377533,698011,362380,677749,347237,662418,333736,644681,320601,631056,308824,616745,296557,603494,286074,593268,275211,581252,264325,573063,253953,562776,244201,551650,234739,544269,224986,536609,216510,525909,207987,519040,200459,512154,191947,504695,184563,497441,177030,488008,170136,479262,162776,472870,155737,465554,150475,456870,143638,449293,137978,440371,131676,432423,125657,423864,120685,415857,115120,408326,110817,399305,104738,390809,99794,382829,94773,372234,90534,362971,85714,355570,80663,345104,77021,336166,72742,326705,68455,317554,64383,307519,59844,298666,56256,290764,52430,281497,49271,272144,46573,264983,42964,256042,40035,246129,36888,239546,34103,230020,47839,115843, 11 | }; 12 | SRLA_STATIC_ASSERT((1 << SRLA_LPC_COEFFICIENT_BITWIDTH) == SRLA_NUM_ARRAY_ELEMENTS(st_parameter_frequency_table)); 13 | 14 | /* 係数のハフマン木 */ 15 | static struct StaticHuffmanTree st_parameter_huffman_tree = { 0, }; 16 | 17 | /* 和を取った係数頻度テーブル */ 18 | static const uint32_t st_sum_parameter_frequency_table[256] = { 19 | 22437965,20905178,21162606,17608395,17960414,13854073,14293033,10708552,10917865,8224103,8339688,6363906,6404030,4947269,4920708,3950293,3887177,3201547,3122802,2650350,2550573,2196893,2083957,1866403,1741521,1603902,1471597,1394642,1250853,1223069,1070520,1065612,922613,948687,789334,849303,690341,767319,604219,694026,531348,631266,469806,578275,415824,528685,370662,477300,329549,438768,288939,405653,259539,375315,232532,350658,209689,325727,190258,303530,172006,283067,154600,264380,141806,247544,127903,233691,116728,213252,106456,200742,97481,189000,86980,178078,78953,168374,72101,157132,66012,149052,60916,139913,56450,134366,52062,127601,48197,121736,44573,115684,41262,110638,38293,106440,36179,101291,33528,96722,31495,93033,28874,89233,27242,84635,25200,80542,22216,77724,20410,74451,19106,71922,18096,68949,16905,65904,15855,62643,14701,60477,14249,57482,13114,56732,12365,55114,11401,50441,10643,47829,9424,45366,8653,41900,7979,39807,7510,36864,6960,34837,6421,32259,5824,28144,5178,26108,4892,24275,4463,22443,3563,21308,3285,19879,2983,18242,2738,17036,2454,16003,2264,15134,2088,14292,1902,13143,1672,12483,1521,11744,1414,10799,1266,10390,1128,9598,1028,9336,932,8646,823,8341,755,7993,584,7450,531,7375,589,6971,545,6711,423,6475,336,6108,360,5812,300,5734,296,5398,271,5158,291,5060,256,4912,242,4760,252,4334,183,4253,189,4220,172,4226,165,4291,141,4491,144,4454,116,4308,139,3879,135,3302,107,2947,107,2632,97,2241,77,2000,74,1789,94,1573,72,1434,70,1371,62,1212,75,1116,67,1073,80,911, 20 | }; 21 | SRLA_STATIC_ASSERT((1 << SRLA_LPC_COEFFICIENT_BITWIDTH) == SRLA_NUM_ARRAY_ELEMENTS(st_sum_parameter_frequency_table)); 22 | 23 | /* 和を取った係数のハフマン木 */ 24 | static struct StaticHuffmanTree st_sum_parameter_huffman_tree = { 0, }; 25 | 26 | /* マージンリスト候補配列 */ 27 | static const double margin_list[] = { 0.0, 1.0 / 4096, 1.0 / 1024, 1.0 / 256, 1.0 / 64, 1.0 / 16 }; 28 | 29 | /* パラメータプリセット配列 */ 30 | const struct SRLAParameterPreset g_srla_parameter_preset[] = { 31 | { 0, SRLA_CH_PROCESS_METHOD_TACTICS_ADAPTIVE, SRLA_LPC_ORDER_DECISION_TACTICS_MAX_FIXED, 0, SRLA_DEFINE_ARRAY_AND_NUM_ELEMTNS_TUPLE(margin_list) }, 32 | { 8, SRLA_CH_PROCESS_METHOD_TACTICS_ADAPTIVE, SRLA_LPC_ORDER_DECISION_TACTICS_BRUTEFORCE_ESTIMATION, 0, SRLA_DEFINE_ARRAY_AND_NUM_ELEMTNS_TUPLE(margin_list) }, 33 | { 16, SRLA_CH_PROCESS_METHOD_TACTICS_ADAPTIVE, SRLA_LPC_ORDER_DECISION_TACTICS_BRUTEFORCE_ESTIMATION, 0, SRLA_DEFINE_ARRAY_AND_NUM_ELEMTNS_TUPLE(margin_list) }, 34 | { 32, SRLA_CH_PROCESS_METHOD_TACTICS_ADAPTIVE, SRLA_LPC_ORDER_DECISION_TACTICS_BRUTEFORCE_ESTIMATION, 0, SRLA_DEFINE_ARRAY_AND_NUM_ELEMTNS_TUPLE(margin_list) }, 35 | { 64, SRLA_CH_PROCESS_METHOD_TACTICS_ADAPTIVE, SRLA_LPC_ORDER_DECISION_TACTICS_BRUTEFORCE_ESTIMATION, 0, SRLA_DEFINE_ARRAY_AND_NUM_ELEMTNS_TUPLE(margin_list) }, 36 | { 128, SRLA_CH_PROCESS_METHOD_TACTICS_ADAPTIVE, SRLA_LPC_ORDER_DECISION_TACTICS_BRUTEFORCE_ESTIMATION, 0, SRLA_DEFINE_ARRAY_AND_NUM_ELEMTNS_TUPLE(margin_list) }, 37 | { 255, SRLA_CH_PROCESS_METHOD_TACTICS_ADAPTIVE, SRLA_LPC_ORDER_DECISION_TACTICS_BRUTEFORCE_ESTIMATION, 0, SRLA_DEFINE_ARRAY_AND_NUM_ELEMTNS_TUPLE(margin_list) }, 38 | }; 39 | SRLA_STATIC_ASSERT(SRLA_NUM_ARRAY_ELEMENTS(g_srla_parameter_preset) == SRLA_NUM_PARAMETER_PRESETS); 40 | 41 | /* パラメータ符号用のハフマン木を取得 */ 42 | const struct StaticHuffmanTree* SRLA_GetParameterHuffmanTree(void) 43 | { 44 | StaticHuffman_BuildHuffmanTree( 45 | st_parameter_frequency_table, SRLA_NUM_ARRAY_ELEMENTS(st_parameter_frequency_table), 46 | &st_parameter_huffman_tree); 47 | 48 | return &st_parameter_huffman_tree; 49 | } 50 | 51 | /* 和をとったパラメータ符号用のハフマン木を取得 */ 52 | const struct StaticHuffmanTree* SRLA_GetSumParameterHuffmanTree(void) 53 | { 54 | StaticHuffman_BuildHuffmanTree( 55 | st_sum_parameter_frequency_table, SRLA_NUM_ARRAY_ELEMENTS(st_sum_parameter_frequency_table), 56 | &st_sum_parameter_huffman_tree); 57 | 58 | return &st_sum_parameter_huffman_tree; 59 | } 60 | -------------------------------------------------------------------------------- /libs/srla_internal/src/srla_utility.c: -------------------------------------------------------------------------------- 1 | #include "srla_utility.h" 2 | 3 | #include 4 | #include 5 | #include "srla_internal.h" 6 | 7 | /* NLZ計算のためのテーブル */ 8 | #define UNUSED 99 9 | static const uint32_t st_nlz10_table[64] = { 10 | 32, 20, 19, UNUSED, UNUSED, 18, UNUSED, 7, 11 | 10, 17, UNUSED, UNUSED, 14, UNUSED, 6, UNUSED, 12 | UNUSED, 9, UNUSED, 16, UNUSED, UNUSED, 1, 26, 13 | UNUSED, 13, UNUSED, UNUSED, 24, 5, UNUSED, UNUSED, 14 | UNUSED, 21, UNUSED, 8, 11, UNUSED, 15, UNUSED, 15 | UNUSED, UNUSED, UNUSED, 2, 27, 0, 25, UNUSED, 16 | 22, UNUSED, 12, UNUSED, UNUSED, 3, 28, UNUSED, 17 | 23, UNUSED, 4, 29, UNUSED, UNUSED, 30, 31 18 | }; 19 | #undef UNUSED 20 | 21 | /* round関数(C89で用意されていない) */ 22 | double SRLAUtility_Round(double d) 23 | { 24 | return (d >= 0.0) ? floor(d + 0.5) : -floor(-d + 0.5); 25 | } 26 | 27 | /* log2関数(C89で定義されていない) */ 28 | double SRLAUtility_Log2(double d) 29 | { 30 | #define INV_LOGE2 (1.4426950408889634) /* 1 / log(2) */ 31 | return log(d) * INV_LOGE2; 32 | #undef INV_LOGE2 33 | } 34 | 35 | /* フレッチャーのチェックサム計算 */ 36 | uint16_t SRLAUtility_CalculateFletcher16CheckSum(const uint8_t *data, size_t data_size) 37 | { 38 | #define MAX_BLOCK_SIZE 5802 /* c1のmodが変化しないブロックサイズ */ 39 | #define MOD255(x) (((x) + ((x) / 255)) & 0xFF) /* 255の剰余計算 */ 40 | uint32_t c0, c1; 41 | 42 | /* 引数チェック */ 43 | SRLA_ASSERT(data != NULL); 44 | 45 | c0 = c1 = 0; 46 | while (data_size > 0) { 47 | size_t block_size = SRLAUTILITY_MIN(MAX_BLOCK_SIZE, data_size); 48 | data_size -= block_size; 49 | while (block_size--) { 50 | c0 += *data++; 51 | c1 += c0; 52 | } 53 | c0 = MOD255(c0); 54 | c1 = MOD255(c1); 55 | } 56 | 57 | return (uint16_t)((c1 << 8) | c0); 58 | #undef MOD255 59 | #undef MAX_BLOCK_SIZE 60 | } 61 | 62 | /* NLZ(最上位ビットから1に当たるまでのビット数)の計算 */ 63 | uint32_t SRLAUtility_NLZSoft(uint32_t x) 64 | { 65 | /* ハッカーのたのしみ参照 */ 66 | x = x | (x >> 1); 67 | x = x | (x >> 2); 68 | x = x | (x >> 4); 69 | x = x | (x >> 8); 70 | x = x & ~(x >> 16); 71 | x = (x << 9) - x; 72 | x = (x << 11) - x; 73 | x = (x << 14) - x; 74 | return st_nlz10_table[x >> 26]; 75 | } 76 | 77 | /* 2の冪乗数に切り上げる */ 78 | uint32_t SRLAUtility_RoundUp2PoweredSoft(uint32_t val) 79 | { 80 | /* ハッカーのたのしみ参照 */ 81 | val--; 82 | val |= val >> 1; 83 | val |= val >> 2; 84 | val |= val >> 4; 85 | val |= val >> 8; 86 | val |= val >> 16; 87 | return val + 1; 88 | } 89 | 90 | /* LR -> MS (in-place) */ 91 | void SRLAUtility_LRtoMSConversion(int32_t **buffer, uint32_t num_samples) 92 | { 93 | uint32_t smpl; 94 | 95 | SRLA_ASSERT(buffer != NULL); 96 | SRLA_ASSERT(buffer[0] != NULL); 97 | SRLA_ASSERT(buffer[1] != NULL); 98 | 99 | for (smpl = 0; smpl < num_samples; smpl++) { 100 | buffer[1][smpl] -= buffer[0][smpl]; 101 | buffer[0][smpl] += (buffer[1][smpl] >> 1); 102 | } 103 | } 104 | 105 | /* MS -> LR (in-place) */ 106 | void SRLAUtility_MStoLRConversion(int32_t **buffer, uint32_t num_samples) 107 | { 108 | uint32_t smpl; 109 | 110 | SRLA_ASSERT(buffer != NULL); 111 | SRLA_ASSERT(buffer[0] != NULL); 112 | SRLA_ASSERT(buffer[1] != NULL); 113 | 114 | for (smpl = 0; smpl < num_samples; smpl++) { 115 | buffer[0][smpl] -= (buffer[1][smpl] >> 1); 116 | buffer[1][smpl] += buffer[0][smpl]; 117 | } 118 | } 119 | 120 | /* LR -> LS (in-place) */ 121 | void SRLAUtility_LRtoLSConversion(int32_t **buffer, uint32_t num_samples) 122 | { 123 | uint32_t smpl; 124 | 125 | SRLA_ASSERT(buffer != NULL); 126 | SRLA_ASSERT(buffer[0] != NULL); 127 | SRLA_ASSERT(buffer[1] != NULL); 128 | 129 | for (smpl = 0; smpl < num_samples; smpl++) { 130 | buffer[1][smpl] -= buffer[0][smpl]; 131 | } 132 | } 133 | 134 | /* LS -> LR (in-place) */ 135 | void SRLAUtility_LStoLRConversion(int32_t **buffer, uint32_t num_samples) 136 | { 137 | uint32_t smpl; 138 | 139 | SRLA_ASSERT(buffer != NULL); 140 | SRLA_ASSERT(buffer[0] != NULL); 141 | SRLA_ASSERT(buffer[1] != NULL); 142 | 143 | for (smpl = 0; smpl < num_samples; smpl++) { 144 | buffer[1][smpl] += buffer[0][smpl]; 145 | } 146 | } 147 | 148 | /* LR -> SR (in-place) */ 149 | void SRLAUtility_LRtoSRConversion(int32_t **buffer, uint32_t num_samples) 150 | { 151 | uint32_t smpl; 152 | 153 | SRLA_ASSERT(buffer != NULL); 154 | SRLA_ASSERT(buffer[0] != NULL); 155 | SRLA_ASSERT(buffer[1] != NULL); 156 | 157 | for (smpl = 0; smpl < num_samples; smpl++) { 158 | buffer[0][smpl] = buffer[1][smpl] - buffer[0][smpl]; 159 | } 160 | } 161 | 162 | /* SR -> LR (in-place) */ 163 | void SRLAUtility_SRtoLRConversion(int32_t **buffer, uint32_t num_samples) 164 | { 165 | uint32_t smpl; 166 | 167 | SRLA_ASSERT(buffer != NULL); 168 | SRLA_ASSERT(buffer[0] != NULL); 169 | SRLA_ASSERT(buffer[1] != NULL); 170 | 171 | for (smpl = 0; smpl < num_samples; smpl++) { 172 | buffer[0][smpl] = buffer[1][smpl] - buffer[0][smpl]; 173 | } 174 | } 175 | 176 | /* プリエンファシスフィルタ初期化 */ 177 | void SRLAPreemphasisFilter_Initialize(struct SRLAPreemphasisFilter *preem) 178 | { 179 | SRLA_ASSERT(preem != NULL); 180 | preem->prev = 0; 181 | preem->coef = 0; 182 | } 183 | 184 | /* 多段プリエンファシスの係数計算 */ 185 | void SRLAPreemphasisFilter_CalculateMultiStageCoefficients( 186 | struct SRLAPreemphasisFilter *preem, uint32_t num_preem, const int32_t *buffer, uint32_t num_samples) 187 | { 188 | uint32_t i; 189 | double r0, r1, r2; 190 | double curr, succ; 191 | double double_coef[SRLA_NUM_PREEMPHASIS_FILTERS]; 192 | 193 | /* 注意)現段階では2回を前提 */ 194 | SRLA_STATIC_ASSERT(SRLA_NUM_PREEMPHASIS_FILTERS == 2); 195 | SRLA_ASSERT(num_preem == 2); 196 | 197 | SRLA_ASSERT(preem != NULL); 198 | SRLA_ASSERT(buffer != NULL); 199 | 200 | /* 相関の計算 */ 201 | curr = buffer[0]; 202 | succ = buffer[1]; 203 | r0 = r1 = r2 = 0.0; 204 | for (i = 0; i < num_samples - 2; i++) { 205 | const double succsucc = buffer[i + 2]; 206 | r0 += curr * curr; 207 | r1 += curr * succ; 208 | r2 += curr * succsucc; 209 | curr = succ; 210 | succ = succsucc; 211 | } 212 | /* i = num_samples - 1 */ 213 | r0 += curr * curr; 214 | r1 += curr * succ; 215 | curr = succ; 216 | r0 += curr * curr; 217 | SRLA_ASSERT((r0 >= r1) && (r0 >= r2)); 218 | 219 | /* 分散が小さい場合は全て0を設定 */ 220 | if (r0 < 1e-6) { 221 | for (i = 0; i < SRLA_NUM_PREEMPHASIS_FILTERS; i++) { 222 | preem[i].coef = 0; 223 | } 224 | return; 225 | } 226 | 227 | /* 分散(=0次相関)で正規化 */ 228 | r1 /= r0; 229 | r2 /= r0; 230 | r0 = 1.0; 231 | 232 | /* プリエンファシスの係数計算 */ 233 | { 234 | /* 平方根の2乗 */ 235 | const double sqroot = r1 * r1 * (r0 - r2) * (r0 - r2) - 4.0 * (r0 * r0 - r1 * r1) * (r1 * r1 - r0 * r2); 236 | if (sqroot >= 0.0) { 237 | double det; 238 | double tmpcoef[2] = { 0.0, 0.0 }; 239 | tmpcoef[1] = (r1 * (r0 - r2) - sqrt(sqroot)) / (2.0 * (r0 * r0 - r1 * r1)); 240 | tmpcoef[0] = (tmpcoef[1] * r1 - r2) / (tmpcoef[1] * r0 - r1); 241 | /* ヘッセ行列の行列式 */ 242 | det = 4.0 * (tmpcoef[0] * tmpcoef[0] * r0 - 2.0 * tmpcoef[0] * r1 + r0) * (tmpcoef[1] * tmpcoef[1] * r0 - 2.0 * tmpcoef[1] * r1 + r0); 243 | det -= 4.0 * pow(2.0 * tmpcoef[0] * tmpcoef[1] * r0 - 2.0 * tmpcoef[0] * r1 - 2.0 * tmpcoef[1] * r1 + r0 + r2, 2.0); 244 | if (det > 0.0) { 245 | double_coef[0] = tmpcoef[0]; 246 | double_coef[1] = tmpcoef[1]; 247 | } else { 248 | double_coef[0] = r1; 249 | double_coef[1] = r1 * (r1 * r1 - r2) / (1.0 - r1 * r1); 250 | } 251 | } else { 252 | /* 複素数解の場合は従来通りの係数(1段ごとに分散最小)を設定 */ 253 | double_coef[0] = r1; 254 | double_coef[1] = r1 * (r1 * r1 - r2) / (1.0 - r1 * r1); 255 | } 256 | } 257 | 258 | /* 固定小数化 */ 259 | for (i = 0; i < SRLA_NUM_PREEMPHASIS_FILTERS; i++) { 260 | int32_t coef = (int32_t)SRLAUtility_Round(double_coef[i] * pow(2.0f, SRLA_PREEMPHASIS_COEF_SHIFT)); 261 | /* 丸め込み */ 262 | coef = SRLAUTILITY_INNER_VALUE(coef, -(1 << SRLA_PREEMPHASIS_COEF_SHIFT), (1 << SRLA_PREEMPHASIS_COEF_SHIFT) - 1); 263 | preem[i].coef = coef; 264 | } 265 | } 266 | 267 | /* プリエンファシス */ 268 | void SRLAPreemphasisFilter_Preemphasis( 269 | struct SRLAPreemphasisFilter *preem, int32_t *buffer, uint32_t num_samples) 270 | { 271 | uint32_t smpl; 272 | int32_t prev, tmp; 273 | 274 | SRLA_ASSERT(buffer != NULL); 275 | SRLA_ASSERT(preem != NULL); 276 | 277 | prev = preem->prev; 278 | for (smpl = 0; smpl < num_samples; smpl++) { 279 | tmp = buffer[smpl]; 280 | buffer[smpl] -= (prev * preem->coef) >> SRLA_PREEMPHASIS_COEF_SHIFT; 281 | prev = tmp; 282 | } 283 | preem->prev = prev; 284 | } 285 | 286 | /* デエンファシスを複数回適用 */ 287 | void SRLAPreemphasisFilter_MultiStageDeemphasis( 288 | struct SRLAPreemphasisFilter *preem, uint32_t num_preem, int32_t *buffer, uint32_t num_samples) 289 | { 290 | uint32_t smpl; 291 | const int32_t c0 = preem[0].coef; 292 | const int32_t c1 = preem[1].coef; 293 | 294 | /* 注意)現段階では2回を前提 */ 295 | SRLA_STATIC_ASSERT(SRLA_NUM_PREEMPHASIS_FILTERS == 2); 296 | SRLA_ASSERT(num_preem == 2); 297 | 298 | SRLA_ASSERT(buffer != NULL); 299 | SRLA_ASSERT(preem != NULL); 300 | 301 | buffer[0] += (preem[1].prev * c1) >> SRLA_PREEMPHASIS_COEF_SHIFT; 302 | buffer[1] += (buffer[0] * c1) >> SRLA_PREEMPHASIS_COEF_SHIFT; 303 | buffer[0] += (preem[0].prev * c0) >> SRLA_PREEMPHASIS_COEF_SHIFT; 304 | 305 | for (smpl = 2; smpl < num_samples; smpl++) { 306 | buffer[smpl] += (buffer[smpl - 1] * c1) >> SRLA_PREEMPHASIS_COEF_SHIFT; 307 | buffer[smpl - 1] += (buffer[smpl - 2] * c0) >> SRLA_PREEMPHASIS_COEF_SHIFT; 308 | } 309 | 310 | preem[0].prev = buffer[num_samples - 1]; 311 | buffer[num_samples - 1] += (buffer[num_samples - 2] * c0) >> SRLA_PREEMPHASIS_COEF_SHIFT; 312 | preem[1].prev = buffer[num_samples - 1]; 313 | } 314 | -------------------------------------------------------------------------------- /libs/static_huffman/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # プロジェクト名 6 | project(StaticHuffman C) 7 | 8 | # ライブラリ名 9 | set(LIB_NAME static_huffman) 10 | 11 | # 静的ライブラリ指定 12 | add_library(${LIB_NAME} STATIC) 13 | 14 | # ソースディレクトリ 15 | add_subdirectory(src) 16 | 17 | # インクルードパス 18 | target_include_directories(${LIB_NAME} 19 | PRIVATE 20 | ${PROJECT_ROOT_PATH}/include 21 | ${PROJECT_ROOT_PATH}/libs/bit_stream/include 22 | PUBLIC 23 | ${CMAKE_CURRENT_SOURCE_DIR}/include 24 | ) 25 | 26 | # コンパイルオプション 27 | if(MSVC) 28 | target_compile_options(${LIB_NAME} PRIVATE /W4) 29 | else() 30 | target_compile_options(${LIB_NAME} PRIVATE -Wall -Wextra -Wpedantic -Wformat=2 -Wstrict-aliasing=2 -Wconversion -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition) 31 | set(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -DDEBUG") 32 | set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") 33 | endif() 34 | set_target_properties(${LIB_NAME} 35 | PROPERTIES 36 | C_STANDARD 90 C_EXTENSIONS OFF 37 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 38 | ) 39 | -------------------------------------------------------------------------------- /libs/static_huffman/include/static_huffman.h: -------------------------------------------------------------------------------- 1 | #ifndef STATICHUFFMAN_H_INCLUDED 2 | #define STATICHUFFMAN_H_INCLUDED 3 | 4 | #include 5 | #include "bit_stream.h" 6 | 7 | /* 符号化するシンボルの最大数 */ 8 | #define STATICHUFFMAN_MAX_NUM_SYMBOLS 256 9 | 10 | /* ハフマン木 */ 11 | struct StaticHuffmanTree { 12 | uint32_t num_symbols; /* 符号化シンボル数 */ 13 | uint32_t root_node; /* 根ノードのインデックス */ 14 | struct { 15 | uint32_t node_0; /* 左側の子供のインデックス */ 16 | uint32_t node_1; /* 右側の子供のインデックス */ 17 | } nodes[2 * STATICHUFFMAN_MAX_NUM_SYMBOLS]; /* 木のノード */ 18 | }; 19 | 20 | /* ハフマン符号 */ 21 | struct StaticHuffmanCodes { 22 | uint32_t num_symbols; /* 符号化シンボル数 */ 23 | struct { 24 | uint32_t code; /* 割り当てたコード(最長32bit) */ 25 | uint8_t bit_count; /* コード長 */ 26 | } codes[STATICHUFFMAN_MAX_NUM_SYMBOLS]; /* 各シンボルの符号 */ 27 | }; 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | /* ハフマン木の構築 */ 34 | void StaticHuffman_BuildHuffmanTree( 35 | const uint32_t *symbol_counts, uint32_t num_symbols, struct StaticHuffmanTree *tree); 36 | 37 | /* 符号テーブル作成 */ 38 | void StaticHuffman_ConvertTreeToCodes( 39 | const struct StaticHuffmanTree *tree, struct StaticHuffmanCodes *codes); 40 | 41 | /* ハフマン符号の出力 */ 42 | void StaticHuffman_PutCode( 43 | const struct StaticHuffmanCodes *codes, struct BitStream *stream, uint32_t val); 44 | 45 | /* ハフマン符号の取得 */ 46 | uint32_t StaticHuffman_GetCode( 47 | const struct StaticHuffmanTree *tree, struct BitStream *stream); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif /* STATICHUFFMAN_H_INCLUDED */ 54 | -------------------------------------------------------------------------------- /libs/static_huffman/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${LIB_NAME} 2 | PRIVATE 3 | ${CMAKE_CURRENT_SOURCE_DIR}/static_huffman.c 4 | ) 5 | -------------------------------------------------------------------------------- /libs/static_huffman/src/static_huffman.c: -------------------------------------------------------------------------------- 1 | #include "static_huffman.h" 2 | #include 3 | #include 4 | 5 | /* カウントの正規化 */ 6 | static void StaticHuffman_NormalizeSymbolCounts( 7 | const uint32_t *symbol_counts, uint32_t num_symbols, 8 | uint32_t *normalized_counts, uint32_t normalized_counts_size) 9 | { 10 | uint32_t node; 11 | 12 | assert((symbol_counts != NULL) && (normalized_counts != NULL)); 13 | assert((2 * num_symbols) <= normalized_counts_size); 14 | 15 | /* 頻度を作業領域にコピー */ 16 | memset(normalized_counts, 0, sizeof(uint32_t) * normalized_counts_size); 17 | memcpy(normalized_counts, symbol_counts, sizeof(uint32_t) * num_symbols); 18 | 19 | /* 0(無効値)の回避 */ 20 | for (node = 0; node < num_symbols; node++) { 21 | if (normalized_counts[node] == 0) { 22 | normalized_counts[node] += 1; 23 | } 24 | } 25 | } 26 | 27 | /* ハフマン符号の構築 */ 28 | void StaticHuffman_BuildHuffmanTree( 29 | const uint32_t *symbol_counts, uint32_t num_symbols, struct StaticHuffmanTree *tree) 30 | { 31 | #define SENTINEL_NODE (2 * STATICHUFFMAN_MAX_NUM_SYMBOLS) 32 | uint32_t min1, min2; /* min1が最小頻度、min2が2番目の最小頻度 */ 33 | uint32_t free_node, node; 34 | uint32_t counts_work[(2 * STATICHUFFMAN_MAX_NUM_SYMBOLS) + 1]; /* シンボルの頻度(番兵ノードで1つ分追加) */ 35 | 36 | assert((symbol_counts != NULL) && (tree != NULL)); 37 | assert(num_symbols > 0); 38 | assert(num_symbols <= STATICHUFFMAN_MAX_NUM_SYMBOLS); 39 | 40 | /* シンボル数を設定 */ 41 | tree->num_symbols = num_symbols; 42 | 43 | /* 頻度カウントの正規化 */ 44 | StaticHuffman_NormalizeSymbolCounts( 45 | symbol_counts, num_symbols, counts_work, 2 * STATICHUFFMAN_MAX_NUM_SYMBOLS); 46 | /* 番兵ノードに最大頻度を設定 */ 47 | counts_work[SENTINEL_NODE] = UINT32_MAX; 48 | 49 | /* 親ノードの作成: num_symbols以降のノードを使用 */ 50 | for (free_node = num_symbols; ; free_node++) { 51 | /* インデックスを番兵に設定 */ 52 | min1 = min2 = SENTINEL_NODE; 53 | 54 | /* 1,2番目の最小値を与えるインデックスを求める */ 55 | /* 最初は全てのノードから始め、次回以降は2つのノードを含んだ 56 | * 親ノードも含める形で最小値を与えるインデックスを探す */ 57 | for (node = 0; node < free_node; node++) { 58 | /* 注目しているノードの頻度が無効値(0)でない時のみ参照 */ 59 | if (counts_work[node] > 0) { 60 | if (counts_work[node] < counts_work[min1]) { 61 | min2 = min1; 62 | min1 = node; 63 | } else if (counts_work[node] < counts_work[min2]) { 64 | min2 = node; 65 | } 66 | } 67 | } 68 | assert(min1 != SENTINEL_NODE); 69 | 70 | /* 2番目の最小値が見つからなかった */ 71 | /* -> ノードが1つになるまでまとまっている。木の根が求まった状態 */ 72 | if (min2 == SENTINEL_NODE) { 73 | break; 74 | } 75 | 76 | /* 親ノードに情報を詰める */ 77 | /* 親ノードの頻度は子の和 */ 78 | counts_work[free_node] = counts_work[min1] + counts_work[min2]; 79 | /* 子ノードの頻度は無効値に */ 80 | counts_work[min1] = counts_work[min2] = 0; 81 | /* 子ノードのインデックスを記録 */ 82 | tree->nodes[free_node].node_0 = min1; 83 | tree->nodes[free_node].node_1 = min2; 84 | } 85 | 86 | assert(free_node <= (2 * STATICHUFFMAN_MAX_NUM_SYMBOLS)); 87 | 88 | /* for文でインクリメントした後なので、1減らして根を記録 */ 89 | tree->root_node = free_node - 1; 90 | 91 | #undef SENTINEL_NODE 92 | } 93 | 94 | /* ハフマン木から符号を構築 */ 95 | static void StaticHuffman_ConvertTreeToCodesCore( 96 | const struct StaticHuffmanTree *tree, struct StaticHuffmanCodes *codes, 97 | uint32_t node, uint32_t code, uint8_t bit_count) 98 | { 99 | assert(tree != NULL); 100 | assert(codes != NULL); 101 | 102 | /* 参照しているノードインデックスが葉に到達している */ 103 | if (node < tree->num_symbols) { 104 | /* コードとビット数を割り当てる */ 105 | codes->codes[node].code = code; 106 | codes->codes[node].bit_count = bit_count; 107 | return; 108 | } 109 | 110 | /* 符号を1ビット分長くする */ 111 | code <<= 1; 112 | bit_count++; 113 | 114 | /* 左側の葉を辿る 符号の最下位ビットには0が追記される */ 115 | StaticHuffman_ConvertTreeToCodesCore(tree, codes, tree->nodes[node].node_0, code | 0, bit_count); 116 | /* 右側の葉を辿る 符号の最下位ビットには1が追記される */ 117 | StaticHuffman_ConvertTreeToCodesCore(tree, codes, tree->nodes[node].node_1, code | 1, bit_count); 118 | } 119 | 120 | /* 符号テーブル作成 */ 121 | void StaticHuffman_ConvertTreeToCodes( 122 | const struct StaticHuffmanTree *tree, struct StaticHuffmanCodes *codes) 123 | { 124 | assert((tree != NULL) && (codes != NULL)); 125 | 126 | /* シンボル数の記録 */ 127 | codes->num_symbols = tree->num_symbols; 128 | 129 | /* 再帰処理を根から開始 */ 130 | StaticHuffman_ConvertTreeToCodesCore(tree, codes, tree->root_node, 0, 0); 131 | } 132 | 133 | /* ハフマン符号の出力 */ 134 | void StaticHuffman_PutCode( 135 | const struct StaticHuffmanCodes *codes, struct BitStream *stream, uint32_t val) 136 | { 137 | assert(codes != NULL); 138 | assert(stream != NULL); 139 | assert(val < codes->num_symbols); 140 | 141 | BitWriter_PutBits(stream, codes->codes[val].code, codes->codes[val].bit_count); 142 | } 143 | 144 | /* ハフマン符号の取得 */ 145 | uint32_t StaticHuffman_GetCode( 146 | const struct StaticHuffmanTree *tree, struct BitStream *stream) 147 | { 148 | uint32_t node, bit; 149 | 150 | assert(tree != NULL); 151 | assert(stream != NULL); 152 | 153 | /* ノードをルートに設定 */ 154 | node = tree->root_node; 155 | 156 | /* 葉ノードに達するまで木を辿る */ 157 | do { 158 | BitReader_GetBits(stream, &bit, 1); 159 | node = (bit == 0) ? tree->nodes[node].node_0 : tree->nodes[node].node_1; 160 | } while (node >= tree->num_symbols); 161 | 162 | assert(node < tree->num_symbols); 163 | 164 | return node; 165 | } 166 | -------------------------------------------------------------------------------- /libs/wav/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | # プロジェクト名 4 | project(Wav C) 5 | 6 | # ライブラリ名 7 | set(LIB_NAME wav) 8 | 9 | # 静的ライブラリ指定 10 | add_library(${LIB_NAME} STATIC) 11 | 12 | # ソースディレクトリ 13 | add_subdirectory(src) 14 | 15 | # インクルードパス 16 | target_include_directories(${LIB_NAME} 17 | PUBLIC 18 | ${CMAKE_CURRENT_SOURCE_DIR}/include 19 | ) 20 | 21 | # コンパイルオプション 22 | if(MSVC) 23 | target_compile_options(${LIB_NAME} PRIVATE /W4) 24 | else() 25 | target_compile_options(${LIB_NAME} PRIVATE -Wall -Wextra -Wpedantic -Wformat=2 -Wstrict-aliasing=2 -Wconversion -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition) 26 | set(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -DDEBUG") 27 | set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") 28 | endif() 29 | set_target_properties(${LIB_NAME} 30 | PROPERTIES 31 | C_STANDARD 90 C_EXTENSIONS OFF 32 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 33 | ) 34 | -------------------------------------------------------------------------------- /libs/wav/include/wav.h: -------------------------------------------------------------------------------- 1 | #ifndef WAV_INCLUDED 2 | #define WAV_INCLUDED 3 | 4 | #include 5 | 6 | /* PCM型 - ファイルのビット深度如何によらず、メモリ上では全て符号付き32bitで取り扱う */ 7 | typedef int32_t WAVPcmData; 8 | 9 | /* WAVデータのフォーマット */ 10 | typedef enum WAVDataFormatTag { 11 | WAV_DATA_FORMAT_PCM /* PCMのみ対応 */ 12 | } WAVDataFormat; 13 | 14 | /* API結果型 */ 15 | typedef enum WAVApiResultTag { 16 | WAV_APIRESULT_OK = 0, 17 | WAV_APIRESULT_NG, 18 | WAV_APIRESULT_INVALID_FORMAT, /* フォーマットが不正 */ 19 | WAV_APIRESULT_IOERROR, /* ファイル入出力エラー */ 20 | WAV_APIRESULT_INVALID_PARAMETER /* 引数が不正 */ 21 | } WAVApiResult; 22 | 23 | /* WAVファイルフォーマット */ 24 | struct WAVFileFormat { 25 | WAVDataFormat data_format; /* データフォーマット */ 26 | uint32_t num_channels; /* チャンネル数 */ 27 | uint32_t sampling_rate; /* サンプリングレート */ 28 | uint32_t bits_per_sample; /* 量子化ビット数 */ 29 | uint32_t num_samples; /* サンプル数 */ 30 | }; 31 | 32 | /* WAVファイルハンドル */ 33 | struct WAVFile { 34 | struct WAVFileFormat format; /* フォーマット */ 35 | WAVPcmData** data; /* 実データ */ 36 | }; 37 | 38 | /* アクセサ */ 39 | #define WAVFile_PCM(wavfile, samp, ch) (wavfile->data[(ch)][(samp)]) 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | /* ファイルからWAVファイルハンドルを作成 */ 46 | struct WAVFile* WAV_CreateFromFile(const char* filename); 47 | 48 | /* フォーマットを指定して新規にWAVファイルハンドルを作成 */ 49 | struct WAVFile* WAV_Create(const struct WAVFileFormat* format); 50 | 51 | /* WAVファイルハンドルを破棄 */ 52 | void WAV_Destroy(struct WAVFile* wavfile); 53 | 54 | /* ファイル書き出し */ 55 | WAVApiResult WAV_WriteToFile( 56 | const char* filename, const struct WAVFile* wavfile); 57 | 58 | /* ファイルからWAVファイルフォーマットだけ読み取り */ 59 | WAVApiResult WAV_GetWAVFormatFromFile( 60 | const char* filename, struct WAVFileFormat* format); 61 | 62 | #ifdef __cplusplus 63 | } 64 | #endif 65 | 66 | #endif /* WAV_INCLUDED */ 67 | -------------------------------------------------------------------------------- /libs/wav/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${LIB_NAME} 2 | PRIVATE 3 | ${CMAKE_CURRENT_SOURCE_DIR}/wav.c 4 | ) 5 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | add_subdirectory(bit_stream) 4 | add_subdirectory(byte_array) 5 | add_subdirectory(command_line_parser) 6 | add_subdirectory(srla_internal) 7 | add_subdirectory(srla_coder) 8 | add_subdirectory(srla_encoder) 9 | add_subdirectory(srla_decoder) 10 | add_subdirectory(srla_encode_decode) 11 | add_subdirectory(lpc) 12 | add_subdirectory(fft) 13 | add_subdirectory(static_huffman) 14 | add_subdirectory(wav) 15 | -------------------------------------------------------------------------------- /test/bit_stream/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # テスト名 6 | set(TEST_NAME bit_stream_test) 7 | 8 | # 実行形式ファイル 9 | add_executable(${TEST_NAME} main.cpp bit_stream_macro_test.cpp bit_stream_function_test.cpp) 10 | 11 | # インクルードディレクトリ 12 | include_directories(${PROJECT_ROOT_PATH}/libs/bit_stream/include) 13 | 14 | # リンクするライブラリ 15 | target_link_libraries(${TEST_NAME} gtest gtest_main) 16 | if (NOT MSVC) 17 | target_link_libraries(${TEST_NAME} pthread) 18 | endif() 19 | 20 | # コンパイルオプション 21 | set_target_properties(${TEST_NAME} 22 | PROPERTIES 23 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 24 | ) 25 | 26 | add_test( 27 | NAME bit_stream 28 | COMMAND $ 29 | ) 30 | 31 | # run with: ctest -L lib 32 | set_property( 33 | TEST bit_stream 34 | PROPERTY LABELS lib bit_stream 35 | ) 36 | -------------------------------------------------------------------------------- /test/bit_stream/bit_stream_common_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | /* インスタンス作成破棄テスト */ 7 | TEST(BitStreamTest, CreateDestroyTest) 8 | { 9 | /* インスタンス作成・破棄 */ 10 | { 11 | struct BitStream strm; 12 | uint8_t test_memory[] = {'A', 'I', 'K', 'A', 'T', 'S', 'U'}; 13 | const uint32_t test_memory_size = sizeof(test_memory) / sizeof(test_memory[0]); 14 | 15 | /* 書きモードでインスタンス作成 */ 16 | BitWriter_Open(&strm, test_memory, test_memory_size); 17 | EXPECT_TRUE(strm.memory_image == test_memory); 18 | EXPECT_EQ(test_memory_size, strm.memory_size); 19 | EXPECT_TRUE(strm.memory_p == test_memory); 20 | EXPECT_EQ(0, strm.bit_buffer); 21 | EXPECT_EQ(32, strm.bit_count); 22 | EXPECT_TRUE(!(strm.flags & BITSTREAM_FLAGS_MODE_READ)); 23 | BitStream_Close(&strm); 24 | 25 | /* 読みモードでインスタンス作成 */ 26 | BitReader_Open(&strm, test_memory, test_memory_size); 27 | EXPECT_TRUE(strm.memory_image == test_memory); 28 | EXPECT_EQ(test_memory_size, strm.memory_size); 29 | EXPECT_TRUE(strm.memory_p == test_memory); 30 | EXPECT_EQ(0, strm.bit_buffer); 31 | EXPECT_EQ(0, strm.bit_count); 32 | EXPECT_TRUE(strm.flags & BITSTREAM_FLAGS_MODE_READ); 33 | BitStream_Close(&strm); 34 | } 35 | } 36 | 37 | /* PutBit関数テスト */ 38 | TEST(BitStreamTest, PutGetTest) 39 | { 40 | { 41 | struct BitStream strm; 42 | uint8_t bit_pattern[] = { 1, 1, 1, 1, 0, 0, 0, 0 }; 43 | uint8_t memory_image[256]; 44 | uint32_t bit_pattern_length = sizeof(bit_pattern) / sizeof(bit_pattern[0]); 45 | uint32_t i, is_ok; 46 | 47 | /* 書き込んでみる */ 48 | BitWriter_Open(&strm, memory_image, sizeof(memory_image)); 49 | for (i = 0; i < bit_pattern_length; i++) { 50 | BitWriter_PutBits(&strm, bit_pattern[i], 1); 51 | } 52 | BitStream_Close(&strm); 53 | 54 | /* 正しく書き込めているか? */ 55 | BitReader_Open(&strm, memory_image, sizeof(memory_image)); 56 | is_ok = 1; 57 | for (i = 0; i < bit_pattern_length; i++) { 58 | uint32_t buf; 59 | BitReader_GetBits(&strm, &buf, 1); 60 | if ((uint8_t)buf != bit_pattern[i]) { 61 | is_ok = 0; 62 | break; 63 | } 64 | } 65 | EXPECT_EQ(1, is_ok); 66 | BitStream_Close(&strm); 67 | } 68 | 69 | /* PutBit関数テスト2 8bitパターンチェック */ 70 | { 71 | struct BitStream strm; 72 | uint8_t memory_image[256]; 73 | uint32_t i, is_ok, nbits; 74 | 75 | for (nbits = 1; nbits <= 8; nbits++) { 76 | /* 書き込んでみる */ 77 | BitWriter_Open(&strm, memory_image, sizeof(memory_image)); 78 | for (i = 0; i < (1 << nbits); i++) { 79 | BitWriter_PutBits(&strm, i, nbits); 80 | } 81 | BitStream_Close(&strm); 82 | 83 | /* 正しく書き込めているか? */ 84 | BitReader_Open(&strm, memory_image, sizeof(memory_image)); 85 | is_ok = 1; 86 | for (i = 0; i < (1 << nbits); i++) { 87 | uint32_t buf; 88 | BitReader_GetBits(&strm, &buf, nbits); 89 | if (buf != i) { 90 | is_ok = 0; 91 | break; 92 | } 93 | } 94 | EXPECT_EQ(1, is_ok); 95 | BitStream_Close(&strm); 96 | } 97 | 98 | } 99 | 100 | /* Flushテスト */ 101 | { 102 | struct BitStream strm; 103 | uint8_t memory_image[256] = { 0, }; 104 | uint32_t bits; 105 | 106 | BitWriter_Open(&strm, memory_image, sizeof(memory_image)); 107 | BitWriter_PutBits(&strm, 1, 1); 108 | BitWriter_PutBits(&strm, 1, 1); 109 | /* 2bitしか書いていないがフラッシュ */ 110 | BitStream_Flush(&strm); 111 | EXPECT_EQ(0, strm.bit_buffer); 112 | EXPECT_EQ(32, strm.bit_count); 113 | BitStream_Close(&strm); 114 | 115 | /* 1バイトで先頭2bitだけが立っているはず */ 116 | BitReader_Open(&strm, memory_image, sizeof(memory_image)); 117 | BitReader_GetBits(&strm, &bits, 8); 118 | EXPECT_EQ(0xC0, bits); 119 | EXPECT_EQ(24, strm.bit_count); 120 | EXPECT_EQ(0xC0000000, strm.bit_buffer); 121 | EXPECT_EQ(&memory_image[4], strm.memory_p); 122 | BitStream_Flush(&strm); 123 | EXPECT_EQ(0, strm.bit_count); 124 | EXPECT_EQ(0, strm.bit_buffer); 125 | EXPECT_EQ(&memory_image[1], strm.memory_p); 126 | BitStream_Close(&strm); 127 | } 128 | 129 | } 130 | 131 | /* seek, tellなどのストリーム操作系APIテスト */ 132 | TEST(BitStreamTest, StreamOperationTest) 133 | { 134 | /* Seek/Tellテスト */ 135 | { 136 | struct BitStream strm; 137 | int32_t tell_result; 138 | uint8_t test_memory[8]; 139 | 140 | /* テスト用に適当にデータ作成 */ 141 | BitWriter_Open(&strm, test_memory, sizeof(test_memory)); 142 | BitWriter_PutBits(&strm, 0xDEADBEAF, 32); 143 | BitWriter_PutBits(&strm, 0xABADCAFE, 32); 144 | BitStream_Tell(&strm, &tell_result); 145 | EXPECT_EQ(8, tell_result); 146 | BitStream_Close(&strm); 147 | 148 | /* ビットリーダを使ったseek & tellテスト */ 149 | BitReader_Open(&strm, test_memory, sizeof(test_memory)); 150 | BitStream_Seek(&strm, 0, BITSTREAM_SEEK_SET); 151 | BitStream_Tell(&strm, &tell_result); 152 | EXPECT_EQ(0, tell_result); 153 | BitStream_Seek(&strm, 1, BITSTREAM_SEEK_CUR); 154 | BitStream_Tell(&strm, &tell_result); 155 | EXPECT_EQ(1, tell_result); 156 | BitStream_Seek(&strm, 2, BITSTREAM_SEEK_CUR); 157 | BitStream_Tell(&strm, &tell_result); 158 | EXPECT_EQ(3, tell_result); 159 | BitStream_Seek(&strm, 0, BITSTREAM_SEEK_END); 160 | BitStream_Tell(&strm, &tell_result); 161 | EXPECT_EQ(7, tell_result); 162 | BitStream_Close(&strm); 163 | 164 | /* ビットライタを使ったseek & tellテスト */ 165 | BitWriter_Open(&strm, test_memory, sizeof(test_memory)); 166 | BitStream_Seek(&strm, 0, BITSTREAM_SEEK_SET); 167 | BitStream_Tell(&strm, &tell_result); 168 | EXPECT_EQ(0, tell_result); 169 | BitStream_Seek(&strm, 1, BITSTREAM_SEEK_CUR); 170 | BitStream_Tell(&strm, &tell_result); 171 | EXPECT_EQ(1, tell_result); 172 | BitStream_Seek(&strm, 2, BITSTREAM_SEEK_CUR); 173 | BitStream_Tell(&strm, &tell_result); 174 | EXPECT_EQ(3, tell_result); 175 | BitStream_Seek(&strm, 0, BITSTREAM_SEEK_END); 176 | BitStream_Tell(&strm, &tell_result); 177 | EXPECT_EQ(7, tell_result); 178 | BitStream_Close(&strm); 179 | } 180 | } 181 | 182 | /* ランレングス取得テスト */ 183 | TEST(BitStreamTest, GetZeroRunLengthTest) 184 | { 185 | { 186 | struct BitStream strm; 187 | uint8_t data[256] = { 0, }; 188 | uint32_t test_length, run; 189 | 190 | for (test_length = 0; test_length <= 65; test_length++) { 191 | /* ラン長だけ0を書き込み、1で止める */ 192 | BitWriter_Open(&strm, data, sizeof(data)); 193 | for (run = 0; run < test_length; run++) { 194 | BitWriter_PutBits(&strm, 0, 1); 195 | } 196 | BitWriter_PutBits(&strm, 1, 1); 197 | BitStream_Close(&strm); 198 | 199 | BitReader_Open(&strm, data, sizeof(data)); 200 | BitReader_GetZeroRunLength(&strm, &run); 201 | EXPECT_EQ(test_length, run); 202 | } 203 | 204 | /* ラン長出力APIを使用 */ 205 | for (test_length = 0; test_length <= 65; test_length++) { 206 | BitWriter_Open(&strm, data, sizeof(data)); 207 | BitWriter_PutZeroRun(&strm, test_length); 208 | BitStream_Close(&strm); 209 | 210 | BitReader_Open(&strm, data, sizeof(data)); 211 | BitReader_GetZeroRunLength(&strm, &run); 212 | EXPECT_EQ(test_length, run); 213 | } 214 | 215 | /* 連続したラン */ 216 | BitWriter_Open(&strm, data, sizeof(data)); 217 | for (test_length = 0; test_length <= 32; test_length++) { 218 | BitWriter_PutZeroRun(&strm, test_length); 219 | } 220 | BitStream_Close(&strm); 221 | BitReader_Open(&strm, data, sizeof(data)); 222 | for (test_length = 0; test_length <= 32; test_length++) { 223 | BitReader_GetZeroRunLength(&strm, &run); 224 | EXPECT_EQ(test_length, run); 225 | } 226 | BitStream_Close(&strm); 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /test/bit_stream/bit_stream_function_test.cpp: -------------------------------------------------------------------------------- 1 | #include "bit_stream.h" 2 | 3 | /* マクロ定義を削除 */ 4 | #undef BitReader_Open 5 | #undef BitWriter_Open 6 | #undef BitStream_Close 7 | #undef BitStream_Seek 8 | #undef BitStream_Tell 9 | #undef BitWriter_PutBits 10 | #undef BitWriter_PutZeroRun 11 | #undef BitReader_GetBits 12 | #undef BitReader_GetZeroRunLength 13 | #undef BitStream_Flush 14 | 15 | /* マクロの代わりに関数宣言 */ 16 | extern "C" { 17 | void BitReader_Open(struct BitStream *stream, const uint8_t *memory, size_t size); 18 | void BitWriter_Open(struct BitStream *stream, const uint8_t *memory, size_t size); 19 | void BitStream_Close(struct BitStream *stream); 20 | void BitStream_Seek(struct BitStream *stream, int32_t offset, int32_t origin); 21 | void BitStream_Tell(struct BitStream *stream, int32_t *result); 22 | void BitWriter_PutBits(struct BitStream *stream, uint32_t val, uint32_t nbits); 23 | void BitWriter_PutZeroRun(struct BitStream *stream, uint32_t runlength); 24 | void BitReader_GetBits(struct BitStream *stream, uint32_t *val, uint32_t nbits); 25 | void BitReader_GetZeroRunLength(struct BitStream *stream, uint32_t *runlength); 26 | void BitStream_Flush(struct BitStream *stream); 27 | } 28 | 29 | /* 多重定義防止 */ 30 | #define BitStream_NLZSoft BitStream_NLZSoftTestDummy 31 | #define g_bitstream_lower_bits_mask g_bitstream_lower_bits_mask_test_dummy 32 | #define g_bitstream_zerobit_runlength_table g_bitstream_zerobit_runlength_table_test_dummy 33 | 34 | /* テスト対象のモジュール */ 35 | extern "C" { 36 | /* 関数定義を使用 */ 37 | #undef BITSTREAM_USE_MACROS 38 | #include "../../libs/bit_stream/src/bit_stream.c" 39 | } 40 | 41 | /* マクロと同じテストソースを使用 */ 42 | #define BitStreamTest BitStreamFunctionTest 43 | #include "bit_stream_common_test.cpp" 44 | #undef BitStreamTest 45 | -------------------------------------------------------------------------------- /test/bit_stream/bit_stream_macro_test.cpp: -------------------------------------------------------------------------------- 1 | /* テスト対象のモジュール */ 2 | extern "C" { 3 | #include "../../libs/bit_stream/src/bit_stream.c" 4 | } 5 | 6 | #include "bit_stream_common_test.cpp" 7 | -------------------------------------------------------------------------------- /test/bit_stream/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char **argv) 4 | { 5 | ::testing::InitGoogleTest(&argc, argv); 6 | return RUN_ALL_TESTS(); 7 | } 8 | -------------------------------------------------------------------------------- /test/byte_array/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # テスト名 6 | set(TEST_NAME byte_array_test) 7 | 8 | # 実行形式ファイル 9 | add_executable(${TEST_NAME} main.cpp) 10 | 11 | # インクルードディレクトリ 12 | include_directories(${PROJECT_ROOT_PATH}/libs/byte_array/include) 13 | 14 | # リンクするライブラリ 15 | target_link_libraries(${TEST_NAME} gtest gtest_main) 16 | if (NOT MSVC) 17 | target_link_libraries(${TEST_NAME} pthread) 18 | endif() 19 | 20 | # コンパイルオプション 21 | set_target_properties(${TEST_NAME} 22 | PROPERTIES 23 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 24 | ) 25 | 26 | add_test( 27 | NAME byte_array 28 | COMMAND $ 29 | ) 30 | 31 | # run with: ctest -L lib 32 | set_property( 33 | TEST byte_array 34 | PROPERTY LABELS lib byte_array 35 | ) 36 | -------------------------------------------------------------------------------- /test/command_line_parser/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # テスト名 6 | set(TEST_NAME command_line_parser_test) 7 | 8 | # 実行形式ファイル 9 | add_executable(${TEST_NAME} main.cpp) 10 | 11 | # インクルードディレクトリ 12 | include_directories(${PROJECT_ROOT_PATH}/libs/command_line_parser/include) 13 | 14 | # リンクするライブラリ 15 | target_link_libraries(${TEST_NAME} gtest gtest_main) 16 | if (NOT MSVC) 17 | target_link_libraries(${TEST_NAME} pthread) 18 | endif() 19 | 20 | # コンパイルオプション 21 | set_target_properties(${TEST_NAME} 22 | PROPERTIES 23 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 24 | ) 25 | 26 | add_test( 27 | NAME command_line_parser 28 | COMMAND $ 29 | ) 30 | 31 | # run with: ctest -L lib 32 | set_property( 33 | TEST command_line_parser 34 | PROPERTY LABELS lib command_line_parser 35 | ) 36 | -------------------------------------------------------------------------------- /test/fft/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # テスト名 6 | set(TEST_NAME fft_test) 7 | 8 | # 実行形式ファイル 9 | add_executable(${TEST_NAME} main.cpp) 10 | 11 | # インクルードディレクトリ 12 | include_directories(${PROJECT_ROOT_PATH}/libs/fft/include) 13 | 14 | # リンクするライブラリ 15 | target_link_libraries(${TEST_NAME} gtest gtest_main) 16 | if (NOT MSVC) 17 | target_link_libraries(${TEST_NAME} pthread) 18 | endif() 19 | 20 | # コンパイルオプション 21 | set_target_properties(${TEST_NAME} 22 | PROPERTIES 23 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 24 | ) 25 | 26 | add_test( 27 | NAME fft 28 | COMMAND $ 29 | ) 30 | 31 | # run with: ctest -L lib 32 | set_property( 33 | TEST fft 34 | PROPERTY LABELS lib fft 35 | ) 36 | -------------------------------------------------------------------------------- /test/lpc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # テスト名 6 | set(TEST_NAME lpc_test) 7 | 8 | # 実行形式ファイル 9 | add_executable(${TEST_NAME} main.cpp) 10 | 11 | # インクルードディレクトリ 12 | include_directories(${PROJECT_ROOT_PATH}/libs/lpc/include) 13 | 14 | # リンクするライブラリ 15 | target_link_libraries(${TEST_NAME} gtest gtest_main fft) 16 | if (NOT MSVC) 17 | target_link_libraries(${TEST_NAME} pthread) 18 | endif() 19 | 20 | # コンパイルオプション 21 | set_target_properties(${TEST_NAME} 22 | PROPERTIES 23 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 24 | ) 25 | 26 | add_test( 27 | NAME lpc 28 | COMMAND $ 29 | ) 30 | 31 | # run with: ctest -L lib 32 | set_property( 33 | TEST lpc 34 | PROPERTY LABELS lib lpc 35 | ) 36 | -------------------------------------------------------------------------------- /test/lpc/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | /* テスト対象のモジュール */ 7 | extern "C" { 8 | #include "../../libs/lpc/src/lpc.c" 9 | } 10 | 11 | /* ハンドル作成破棄テスト */ 12 | TEST(LPCCalculatorTest, CreateDestroyHandleTest) 13 | { 14 | /* ワークサイズ計算テスト */ 15 | { 16 | int32_t work_size; 17 | struct LPCCalculatorConfig config; 18 | 19 | /* 最低限構造体本体よりは大きいはず */ 20 | config.max_order = 1; 21 | config.max_num_samples = 1; 22 | work_size = LPCCalculator_CalculateWorkSize(&config); 23 | ASSERT_TRUE(work_size > sizeof(struct LPCCalculator)); 24 | 25 | /* 不正なコンフィグ */ 26 | EXPECT_TRUE(LPCCalculator_CalculateWorkSize(0) < 0); 27 | } 28 | 29 | /* ワーク領域渡しによるハンドル作成(成功例) */ 30 | { 31 | void *work; 32 | int32_t work_size; 33 | struct LPCCalculatorConfig config; 34 | struct LPCCalculator *lpcc; 35 | 36 | config.max_order = 1; 37 | config.max_num_samples = 1; 38 | work_size = LPCCalculator_CalculateWorkSize(&config); 39 | work = malloc(work_size); 40 | 41 | lpcc = LPCCalculator_Create(&config, work, work_size); 42 | ASSERT_TRUE(lpcc != NULL); 43 | EXPECT_TRUE(lpcc->work == work); 44 | EXPECT_EQ(lpcc->alloced_by_own, 0); 45 | 46 | LPCCalculator_Destroy(lpcc); 47 | free(work); 48 | } 49 | 50 | /* 自前確保によるハンドル作成(成功例) */ 51 | { 52 | struct LPCCalculator *lpcc; 53 | struct LPCCalculatorConfig config; 54 | 55 | config.max_order = 1; 56 | config.max_num_samples = 1; 57 | lpcc = LPCCalculator_Create(&config, NULL, 0); 58 | ASSERT_TRUE(lpcc != NULL); 59 | EXPECT_TRUE(lpcc->work != NULL); 60 | EXPECT_EQ(lpcc->alloced_by_own, 1); 61 | 62 | LPCCalculator_Destroy(lpcc); 63 | } 64 | 65 | /* ワーク領域渡しによるハンドル作成(失敗ケース) */ 66 | { 67 | void *work; 68 | int32_t work_size; 69 | struct LPCCalculator *lpcc; 70 | struct LPCCalculatorConfig config; 71 | 72 | config.max_order = 1; 73 | config.max_num_samples = 1; 74 | work_size = LPCCalculator_CalculateWorkSize(&config); 75 | work = malloc(work_size); 76 | 77 | /* 引数が不正 */ 78 | lpcc = LPCCalculator_Create(NULL, work, work_size); 79 | EXPECT_TRUE(lpcc == NULL); 80 | lpcc = LPCCalculator_Create(&config, NULL, work_size); 81 | EXPECT_TRUE(lpcc == NULL); 82 | lpcc = LPCCalculator_Create(&config, work, 0); 83 | EXPECT_TRUE(lpcc == NULL); 84 | 85 | /* コンフィグパラメータが不正 */ 86 | config.max_order = 1; config.max_num_samples = 0; 87 | lpcc = LPCCalculator_Create(&config, work, work_size); 88 | EXPECT_TRUE(lpcc == NULL); 89 | 90 | free(work); 91 | } 92 | 93 | /* 自前確保によるハンドル作成(失敗ケース) */ 94 | { 95 | struct LPCCalculator *lpcc; 96 | struct LPCCalculatorConfig config; 97 | 98 | /* コンフィグパラメータが不正 */ 99 | config.max_order = 1; config.max_num_samples = 0; 100 | lpcc = LPCCalculator_Create(&config, NULL, 0); 101 | EXPECT_TRUE(lpcc == NULL); 102 | } 103 | } 104 | 105 | /* (テスト用)PARCOR係数をLPC係数に変換 */ 106 | static LPCError LPC_ConvertPARCORtoLPCDouble( 107 | struct LPCCalculator* lpcc, const double* parcor_coef, uint32_t coef_order, double *lpc_coef) 108 | { 109 | int32_t i, k; 110 | double *a_vec; 111 | 112 | /* 引数チェック */ 113 | if ((lpcc == NULL) || (lpc_coef == NULL) || (parcor_coef == NULL)) { 114 | return LPC_ERROR_INVALID_ARGUMENT; 115 | } 116 | 117 | /* 次数チェック */ 118 | assert(coef_order <= lpcc->max_order); 119 | 120 | /* 作業領域を割り当て */ 121 | a_vec = lpcc->a_vecs[0]; 122 | 123 | /* 再帰計算 */ 124 | lpc_coef[0] = -parcor_coef[0]; 125 | for (i = 1; i < coef_order; i++) { 126 | const double gamma = -parcor_coef[i]; 127 | for (k = 0; k < i; k++) { 128 | a_vec[k] = lpc_coef[k]; 129 | } 130 | for (k = 0; k < i; k++) { 131 | lpc_coef[k] = a_vec[k] + (gamma * a_vec[i - k - 1]); 132 | } 133 | lpc_coef[i] = gamma; 134 | } 135 | 136 | return LPC_ERROR_OK; 137 | } 138 | 139 | /* LPC係数をPARCOR係数に変換するテスト */ 140 | TEST(LPCCalculatorTest, LPC_ConvertLPCandPARCORTest) 141 | { 142 | /* LPC->PARCORの簡単な成功例 */ 143 | { 144 | #define NUM_SAMPLES 32 145 | #define COEF_ORDER 16 146 | uint32_t i; 147 | struct LPCCalculator* lpcc; 148 | struct LPCCalculatorConfig config; 149 | double data[NUM_SAMPLES], lpc_coef[COEF_ORDER], answer[COEF_ORDER], test[COEF_ORDER]; 150 | 151 | for (i = 0; i < NUM_SAMPLES; i++) { 152 | data[i] = sin(0.1 * i); 153 | } 154 | 155 | config.max_num_samples = NUM_SAMPLES; config.max_order = COEF_ORDER; 156 | lpcc = LPCCalculator_Create(&config, NULL, 0); 157 | ASSERT_TRUE(lpcc != NULL); 158 | 159 | /* 係数計算 */ 160 | ASSERT_EQ(LPC_APIRESULT_OK, 161 | LPCCalculator_CalculateLPCCoefficients(lpcc, 162 | data, NUM_SAMPLES, lpc_coef, COEF_ORDER, LPC_WINDOWTYPE_RECTANGULAR, 0.0)); 163 | memcpy(answer, lpcc->parcor_coef, sizeof(double) * COEF_ORDER); 164 | 165 | LPCCalculator_Destroy(lpcc); 166 | 167 | /* LPC->PARCOR変換 */ 168 | lpcc = LPCCalculator_Create(&config, NULL, 0); 169 | EXPECT_EQ(LPC_ERROR_OK, LPC_ConvertLPCtoPARCORDouble(lpcc, lpc_coef, COEF_ORDER, test)); 170 | 171 | /* 一致確認 */ 172 | for (i = 0; i < COEF_ORDER; i++) { 173 | EXPECT_FLOAT_EQ(answer[i], test[i]); 174 | } 175 | 176 | LPCCalculator_Destroy(lpcc); 177 | #undef NUM_SAMPLES 178 | #undef COEF_ORDER 179 | } 180 | 181 | /* PARCOR->LPCの簡単な成功例 */ 182 | { 183 | #define NUM_SAMPLES 32 184 | #define COEF_ORDER 16 185 | uint32_t i; 186 | struct LPCCalculator* lpcc; 187 | struct LPCCalculatorConfig config; 188 | double data[NUM_SAMPLES], lpc_coef[COEF_ORDER], answer[COEF_ORDER], test[COEF_ORDER]; 189 | 190 | for (i = 0; i < NUM_SAMPLES; i++) { 191 | data[i] = sin(0.1 * i); 192 | } 193 | 194 | config.max_num_samples = NUM_SAMPLES; config.max_order = COEF_ORDER; 195 | lpcc = LPCCalculator_Create(&config, NULL, 0); 196 | ASSERT_TRUE(lpcc != NULL); 197 | 198 | ASSERT_EQ(LPC_APIRESULT_OK, 199 | LPCCalculator_CalculateLPCCoefficients(lpcc, 200 | data, NUM_SAMPLES, lpc_coef, COEF_ORDER, LPC_WINDOWTYPE_RECTANGULAR, 0.0)); 201 | memcpy(answer, lpcc->parcor_coef, sizeof(double) * COEF_ORDER); 202 | 203 | LPCCalculator_Destroy(lpcc); 204 | 205 | /* PARCOR->LPC変換 */ 206 | lpcc = LPCCalculator_Create(&config, NULL, 0); 207 | EXPECT_EQ(LPC_ERROR_OK, LPC_ConvertPARCORtoLPCDouble(lpcc, answer, COEF_ORDER, test)); 208 | 209 | for (i = 0; i < COEF_ORDER; i++) { 210 | EXPECT_FLOAT_EQ(lpc_coef[i], test[i]); 211 | } 212 | 213 | LPCCalculator_Destroy(lpcc); 214 | #undef NUM_SAMPLES 215 | #undef COEF_ORDER 216 | } 217 | } 218 | 219 | int main(int argc, char **argv) 220 | { 221 | ::testing::InitGoogleTest(&argc, argv); 222 | return RUN_ALL_TESTS(); 223 | } 224 | -------------------------------------------------------------------------------- /test/srla_coder/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # テスト名 6 | set(TEST_NAME srla_coder_test) 7 | 8 | # 実行形式ファイル 9 | add_executable(${TEST_NAME} main.cpp) 10 | 11 | # インクルードディレクトリ 12 | include_directories(${PROJECT_ROOT_PATH}/libs/srla_coder/include) 13 | 14 | # リンクするライブラリ 15 | target_link_libraries(${TEST_NAME} gtest gtest_main bit_stream static_huffman srla_internal srla_coder) 16 | if (NOT MSVC) 17 | target_link_libraries(${TEST_NAME} pthread) 18 | endif() 19 | 20 | # コンパイルオプション 21 | set_target_properties(${TEST_NAME} 22 | PROPERTIES 23 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 24 | ) 25 | 26 | # 実行パスをtmp以下に 27 | add_test( 28 | NAME srla_coder 29 | WORKING_DIRECTORY $/tmp 30 | COMMAND $ 31 | ) 32 | 33 | # run with: ctest -L lib 34 | set_property( 35 | TEST srla_coder 36 | PROPERTY LABELS lib srla_coder 37 | ) 38 | 39 | # ビルド後にテストリソースを持ってくる 40 | add_custom_command( 41 | TARGET ${TEST_NAME} 42 | POST_BUILD 43 | COMMAND ${CMAKE_COMMAND} -E make_directory $/tmp 44 | COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/PriChanIcon.png $/tmp 45 | ) 46 | -------------------------------------------------------------------------------- /test/srla_coder/PriChanIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/test/srla_coder/PriChanIcon.png -------------------------------------------------------------------------------- /test/srla_decoder/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # テスト名 6 | set(TEST_NAME srla_decoder_test) 7 | 8 | # 実行形式ファイル 9 | add_executable(${TEST_NAME} 10 | srla_decoder_test.cpp 11 | srla_lpc_synthesize_test.cpp 12 | main.cpp 13 | ) 14 | 15 | # インクルードディレクトリ 16 | include_directories(${PROJECT_ROOT_PATH}/libs/srla_decoder/include) 17 | 18 | # リンクするライブラリ 19 | target_link_libraries(${TEST_NAME} gtest gtest_main byte_array bit_stream srla_encoder srla_coder srla_internal lpc fft static_huffman) 20 | if (NOT MSVC) 21 | target_link_libraries(${TEST_NAME} pthread) 22 | endif() 23 | 24 | # コンパイルオプション 25 | set_target_properties(${TEST_NAME} 26 | PROPERTIES 27 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 28 | ) 29 | 30 | add_test( 31 | NAME srla_decoder 32 | COMMAND $ 33 | ) 34 | 35 | # run with: ctest -L lib 36 | set_property( 37 | TEST srla_decoder 38 | PROPERTY LABELS lib srla_decoder 39 | ) 40 | -------------------------------------------------------------------------------- /test/srla_decoder/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char **argv) 4 | { 5 | ::testing::InitGoogleTest(&argc, argv); 6 | return RUN_ALL_TESTS(); 7 | } 8 | -------------------------------------------------------------------------------- /test/srla_decoder/srla_lpc_synthesize_test.cpp: -------------------------------------------------------------------------------- 1 | /* テスト対象のモジュール */ 2 | extern "C" { 3 | #include "../../libs/srla_decoder/src/srla_lpc_synthesize.c" 4 | } 5 | -------------------------------------------------------------------------------- /test/srla_encode_decode/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # テスト名 6 | set(TEST_NAME srla_encode_decode_test) 7 | 8 | # 実行形式ファイル 9 | add_executable(${TEST_NAME} 10 | main.cpp 11 | ) 12 | 13 | # インクルードディレクトリ 14 | include_directories(${PROJECT_ROOT_PATH}/include) 15 | 16 | # リンクするライブラリ 17 | target_link_libraries(${TEST_NAME} gtest gtest_main srla_encoder srla_decoder srla_coder srla_internal byte_array static_huffman bit_stream lpc fft) 18 | if (NOT MSVC) 19 | target_link_libraries(${TEST_NAME} pthread) 20 | endif() 21 | 22 | # コンパイルオプション 23 | set_target_properties(${TEST_NAME} 24 | PROPERTIES 25 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 26 | ) 27 | 28 | add_test( 29 | NAME srla_encode_decode 30 | COMMAND $ 31 | ) 32 | 33 | # run with: ctest -L lib 34 | set_property( 35 | TEST srla_encode_decode 36 | PROPERTY LABELS lib srla_encode_decode 37 | ) 38 | -------------------------------------------------------------------------------- /test/srla_encoder/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # テスト名 6 | set(TEST_NAME srla_encoder_test) 7 | 8 | # 実行形式ファイル 9 | add_executable(${TEST_NAME} 10 | srla_encoder_test.cpp 11 | srla_lpc_predict_test.cpp 12 | main.cpp 13 | ) 14 | 15 | # インクルードディレクトリ 16 | include_directories(${PROJECT_ROOT_PATH}/libs/srla_encoder/include) 17 | 18 | # リンクするライブラリ 19 | target_link_libraries(${TEST_NAME} gtest gtest_main byte_array bit_stream lpc fft srla_internal srla_coder static_huffman) 20 | if (NOT MSVC) 21 | target_link_libraries(${TEST_NAME} pthread) 22 | endif() 23 | 24 | # コンパイルオプション 25 | set_target_properties(${TEST_NAME} 26 | PROPERTIES 27 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 28 | ) 29 | 30 | add_test( 31 | NAME srla_encoder 32 | COMMAND $ 33 | ) 34 | 35 | # run with: ctest -L lib 36 | set_property( 37 | TEST srla_encoder 38 | PROPERTY LABELS lib srla_encoder 39 | ) 40 | -------------------------------------------------------------------------------- /test/srla_encoder/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char **argv) 4 | { 5 | ::testing::InitGoogleTest(&argc, argv); 6 | return RUN_ALL_TESTS(); 7 | } 8 | -------------------------------------------------------------------------------- /test/srla_encoder/srla_lpc_predict_test.cpp: -------------------------------------------------------------------------------- 1 | /* テスト対象のモジュール */ 2 | extern "C" { 3 | #include "../../libs/srla_encoder/src/srla_lpc_predict.c" 4 | } 5 | -------------------------------------------------------------------------------- /test/srla_internal/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # テスト名 6 | set(TEST_NAME srla_internal_test) 7 | 8 | # 実行形式ファイル 9 | add_executable(${TEST_NAME} main.cpp) 10 | 11 | # インクルードディレクトリ 12 | include_directories(${PROJECT_ROOT_PATH}/libs/srla_internal/include) 13 | 14 | # リンクするライブラリ 15 | target_link_libraries(${TEST_NAME} gtest gtest_main bit_stream static_huffman) 16 | if (NOT MSVC) 17 | target_link_libraries(${TEST_NAME} pthread) 18 | endif() 19 | 20 | # コンパイルオプション 21 | set_target_properties(${TEST_NAME} 22 | PROPERTIES 23 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 24 | ) 25 | 26 | # 実行パスをtmp以下に 27 | add_test( 28 | NAME srla_internal 29 | WORKING_DIRECTORY $/tmp 30 | COMMAND $ 31 | ) 32 | 33 | # run with: ctest -L lib 34 | set_property( 35 | TEST srla_internal 36 | PROPERTY LABELS lib srla_internal 37 | ) 38 | 39 | # ビルド後にテストリソースを持ってくる 40 | add_custom_command( 41 | TARGET ${TEST_NAME} 42 | POST_BUILD 43 | COMMAND ${CMAKE_COMMAND} -E make_directory $/tmp 44 | COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/PriChanIcon.png $/tmp 45 | COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/a.wav $/tmp 46 | ) 47 | -------------------------------------------------------------------------------- /test/srla_internal/PriChanIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/test/srla_internal/PriChanIcon.png -------------------------------------------------------------------------------- /test/srla_internal/a.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/test/srla_internal/a.wav -------------------------------------------------------------------------------- /test/srla_internal/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | /* テスト対象のモジュール */ 7 | extern "C" { 8 | #include "../../libs/srla_internal/src/srla_utility.c" 9 | } 10 | 11 | /* Fletcher16の計算テスト */ 12 | TEST(SRLAUtilityTest, CalculateFletcher16Test) 13 | { 14 | /* リファレンス値と一致するか? */ 15 | { 16 | uint32_t i; 17 | uint16_t ret; 18 | 19 | /* テストケース */ 20 | struct Fletcher16TestCaseForString { 21 | const char *string; 22 | size_t string_len; 23 | uint16_t answer; 24 | }; 25 | 26 | static const struct Fletcher16TestCaseForString fletcher16_test_case[] = { 27 | { "abcde", 5, 0xC8F0 }, 28 | { "abcdef", 6, 0x2057 }, 29 | { "abcdefgh", 8, 0x0627 }, 30 | }; 31 | const uint32_t fletcher16_num_test_cases = sizeof(fletcher16_test_case) / sizeof(fletcher16_test_case[0]); 32 | 33 | for (i = 0; i < fletcher16_num_test_cases; i++) { 34 | ret = SRLAUtility_CalculateFletcher16CheckSum( 35 | (const uint8_t *)fletcher16_test_case[i].string, fletcher16_test_case[i].string_len); 36 | EXPECT_EQ(ret, fletcher16_test_case[i].answer); 37 | } 38 | } 39 | 40 | /* 実データでテスト */ 41 | { 42 | struct stat fstat; 43 | uint32_t i, data_size; 44 | uint16_t ret; 45 | uint8_t* data; 46 | FILE* fp; 47 | 48 | /* テストケース */ 49 | struct Fletcher16TestCaseForFile { 50 | const char* filename; 51 | uint16_t answer; 52 | }; 53 | 54 | static const struct Fletcher16TestCaseForFile fletcher16_test_case[] = { 55 | { "a.wav", 0x4C08 }, 56 | { "PriChanIcon.png", 0x6DA9 }, 57 | }; 58 | const uint32_t crc16ibm_num_test_cases 59 | = sizeof(fletcher16_test_case) / sizeof(fletcher16_test_case[0]); 60 | 61 | for (i = 0; i < crc16ibm_num_test_cases; i++) { 62 | stat(fletcher16_test_case[i].filename, &fstat); 63 | data_size = fstat.st_size; 64 | data = (uint8_t*)malloc(fstat.st_size * sizeof(uint8_t)); 65 | 66 | fp = fopen(fletcher16_test_case[i].filename, "rb"); 67 | fread(data, sizeof(uint8_t), data_size, fp); 68 | ret = SRLAUtility_CalculateFletcher16CheckSum(data, data_size); 69 | EXPECT_EQ(ret, fletcher16_test_case[i].answer); 70 | 71 | free(data); 72 | fclose(fp); 73 | } 74 | } 75 | } 76 | 77 | int main(int argc, char **argv) 78 | { 79 | ::testing::InitGoogleTest(&argc, argv); 80 | return RUN_ALL_TESTS(); 81 | } 82 | -------------------------------------------------------------------------------- /test/static_huffman/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # テスト名 6 | set(TEST_NAME static_huffman_test) 7 | 8 | # 実行形式ファイル 9 | add_executable(${TEST_NAME} main.cpp) 10 | 11 | # インクルードディレクトリ 12 | include_directories(${PROJECT_ROOT_PATH}/libs/static_huffman/include) 13 | 14 | # リンクするライブラリ 15 | target_link_libraries(${TEST_NAME} gtest gtest_main bit_stream) 16 | if (NOT MSVC) 17 | target_link_libraries(${TEST_NAME} pthread) 18 | endif() 19 | 20 | # コンパイルオプション 21 | set_target_properties(${TEST_NAME} 22 | PROPERTIES 23 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 24 | ) 25 | 26 | # 実行パスをtmp以下に 27 | add_test( 28 | NAME static_huffman 29 | WORKING_DIRECTORY $/tmp 30 | COMMAND $ 31 | ) 32 | 33 | # run with: ctest -L lib 34 | set_property( 35 | TEST static_huffman 36 | PROPERTY LABELS lib static_huffman 37 | ) 38 | 39 | # ビルド後にテストリソースを持ってくる 40 | file(GLOB TEST_WAVE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.txt) 41 | add_custom_command( 42 | TARGET ${TEST_NAME} 43 | POST_BUILD 44 | COMMAND ${CMAKE_COMMAND} -E make_directory $/tmp 45 | COMMAND ${CMAKE_COMMAND} -E copy ${TEST_WAVE_FILES} $/tmp 46 | ) 47 | -------------------------------------------------------------------------------- /test/static_huffman/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | /* テスト対象のモジュール */ 8 | extern "C" { 9 | #include "../../libs/static_huffman/src/static_huffman.c" 10 | } 11 | 12 | #if 0 13 | /* ノードの再帰的表示 */ 14 | static void StaticHuffman_PrintNode( 15 | const struct StaticHuffmanTree *tree, const uint32_t *counts, 16 | uint32_t node, uint32_t code, uint8_t bit_count) 17 | { 18 | if (node < tree->num_symbols) { 19 | printf("%X counts:%d code:%X len:%d \n", node, counts[node], code, bit_count); 20 | return; 21 | } 22 | 23 | StaticHuffman_PrintNode(tree, counts, tree->nodes[node].node_0, (code << 1) | 0, bit_count + 1); 24 | StaticHuffman_PrintNode(tree, counts, tree->nodes[node].node_1, (code << 1) | 1, bit_count + 1); 25 | } 26 | 27 | /* 全ノード表示 */ 28 | static void StaticHuffman_PrintAllNodes( 29 | const struct StaticHuffmanTree *tree, const uint32_t *counts) 30 | { 31 | StaticHuffman_PrintNode(tree, counts, tree->root_node, 0, 0); 32 | } 33 | #endif 34 | 35 | /* ハフマン木・符号構成テスト */ 36 | TEST(StaticHuffmanTest, BuildHuffmanTreeTest) 37 | { 38 | 39 | /* 簡単な成功例1 */ 40 | { 41 | static const uint32_t counts[] = { 4, 3, 2, 1 }; 42 | uint32_t counts_size = sizeof(counts) / sizeof(counts[0]); 43 | struct StaticHuffmanTree tree; 44 | struct StaticHuffmanCodes codes; 45 | 46 | StaticHuffman_BuildHuffmanTree(counts, counts_size, &tree); 47 | StaticHuffman_ConvertTreeToCodes(&tree, &codes); 48 | 49 | EXPECT_EQ(counts_size, tree.num_symbols); 50 | EXPECT_EQ(0x0, codes.codes[0].code); EXPECT_EQ(1, codes.codes[0].bit_count); 51 | EXPECT_EQ(0x2, codes.codes[1].code); EXPECT_EQ(2, codes.codes[1].bit_count); 52 | EXPECT_EQ(0x7, codes.codes[2].code); EXPECT_EQ(3, codes.codes[2].bit_count); 53 | EXPECT_EQ(0x6, codes.codes[3].code); EXPECT_EQ(3, codes.codes[3].bit_count); 54 | } 55 | 56 | /* 簡単な成功例2 */ 57 | { 58 | static const uint32_t counts[] = { 5, 3, 2, 1, 1 }; 59 | uint32_t counts_size = sizeof(counts) / sizeof(counts[0]); 60 | struct StaticHuffmanTree tree; 61 | struct StaticHuffmanCodes codes; 62 | 63 | StaticHuffman_BuildHuffmanTree(counts, counts_size, &tree); 64 | StaticHuffman_ConvertTreeToCodes(&tree, &codes); 65 | 66 | EXPECT_EQ(counts_size, tree.num_symbols); 67 | EXPECT_EQ(0x0, codes.codes[0].code); EXPECT_EQ(1, codes.codes[0].bit_count); 68 | EXPECT_EQ(0x2, codes.codes[1].code); EXPECT_EQ(2, codes.codes[1].bit_count); 69 | EXPECT_EQ(0x6, codes.codes[2].code); EXPECT_EQ(3, codes.codes[2].bit_count); 70 | EXPECT_EQ(0xE, codes.codes[3].code); EXPECT_EQ(4, codes.codes[3].bit_count); 71 | EXPECT_EQ(0xF, codes.codes[4].code); EXPECT_EQ(4, codes.codes[4].bit_count); 72 | } 73 | 74 | /* 平均符号長による確認 */ 75 | { 76 | #define NUM_ARRAY_ELEMENTS(array) sizeof(array) / sizeof(array[0]) 77 | struct HuffmanCodeTestCase { 78 | const uint32_t *symbol_counts; 79 | uint32_t num_symbols; 80 | uint32_t sum_code_length_answer; 81 | }; 82 | uint32_t test; 83 | static const uint32_t counts1[] = { 8, 4, 4, 4, 2, 2 }; 84 | static const uint32_t counts2[] = { 50, 20, 10, 8, 5, 4, 2, 1 }; 85 | static const struct HuffmanCodeTestCase test_cases[] = { 86 | { counts1, NUM_ARRAY_ELEMENTS(counts1), 60, }, 87 | { counts2, NUM_ARRAY_ELEMENTS(counts2), 220, }, 88 | }; 89 | const uint32_t num_test_cases = NUM_ARRAY_ELEMENTS(test_cases); 90 | 91 | for (test = 0; test < num_test_cases; test++) { 92 | uint32_t symbol, sum_code_length; 93 | struct StaticHuffmanTree tree; 94 | struct StaticHuffmanCodes codes; 95 | const struct HuffmanCodeTestCase *ptest = &test_cases[test]; 96 | 97 | StaticHuffman_BuildHuffmanTree(ptest->symbol_counts, ptest->num_symbols, &tree); 98 | StaticHuffman_ConvertTreeToCodes(&tree, &codes); 99 | ASSERT_EQ(ptest->num_symbols, tree.num_symbols); 100 | 101 | sum_code_length = 0; 102 | for (symbol = 0; symbol < tree.num_symbols; symbol++) { 103 | sum_code_length += ptest->symbol_counts[symbol] * codes.codes[symbol].bit_count; 104 | } 105 | EXPECT_EQ(ptest->sum_code_length_answer, sum_code_length); 106 | } 107 | #undef NUM_ARRAY_ELEMENTS 108 | } 109 | } 110 | 111 | /* エンコードデコードテスト */ 112 | TEST(StaticHuffmanTest, PutGetCodeTest) 113 | { 114 | /* 簡単な例 */ 115 | { 116 | #define NUM_SYMBOLS 100 117 | uint32_t symbol; 118 | uint32_t counts[NUM_SYMBOLS]; 119 | uint8_t buffer[NUM_SYMBOLS]; 120 | struct StaticHuffmanTree tree; 121 | struct StaticHuffmanCodes codes; 122 | struct BitStream stream; 123 | 124 | /* 全シンボルが等しく出てくるとする */ 125 | for (symbol = 0; symbol < NUM_SYMBOLS; symbol++) { 126 | counts[symbol] = 1; 127 | } 128 | 129 | StaticHuffman_BuildHuffmanTree(counts, NUM_SYMBOLS, &tree); 130 | StaticHuffman_ConvertTreeToCodes(&tree, &codes); 131 | 132 | /* 出力 */ 133 | BitWriter_Open(&stream, buffer, NUM_SYMBOLS); 134 | for (symbol = 0; symbol < NUM_SYMBOLS; symbol++) { 135 | StaticHuffman_PutCode(&codes, &stream, symbol); 136 | } 137 | BitStream_Flush(&stream); 138 | 139 | /* 符号取得/一致確認 */ 140 | BitReader_Open(&stream, buffer, NUM_SYMBOLS); 141 | for (symbol = 0; symbol < NUM_SYMBOLS; symbol++) { 142 | const uint32_t test = StaticHuffman_GetCode(&tree, &stream); 143 | EXPECT_EQ(symbol, test); 144 | } 145 | #undef NUM_SYMBOLS 146 | } 147 | 148 | /* テキストを圧縮・展開してみる */ 149 | { 150 | #define FILENAME "test.txt" 151 | FILE *fp; 152 | uint32_t counts[256]; 153 | uint8_t *data, *buffer; 154 | uint32_t i, file_size, output_size; 155 | struct stat filestat; 156 | struct StaticHuffmanTree tree; 157 | struct StaticHuffmanCodes codes; 158 | struct BitStream stream; 159 | 160 | /* ファイルサイズ計算 */ 161 | stat(FILENAME, &filestat); 162 | file_size = filestat.st_size; 163 | data = (uint8_t *)malloc(file_size); 164 | buffer = (uint8_t *)malloc(2 * file_size); /* 2倍までは増えないと想定 */ 165 | 166 | /* ファイルデータ読み出し */ 167 | fp = fopen(FILENAME, "rb"); 168 | assert(fp != NULL); 169 | fread(data, sizeof(uint8_t), file_size, fp); 170 | fclose(fp); 171 | 172 | /* シンボル頻度計測 */ 173 | memset(counts, 0, sizeof(uint32_t) * 256); 174 | for (i = 0; i < file_size; i++) { 175 | counts[data[i] & 0xFF]++; 176 | } 177 | 178 | StaticHuffman_BuildHuffmanTree(counts, 256, &tree); 179 | StaticHuffman_ConvertTreeToCodes(&tree, &codes); 180 | 181 | /* 出力 */ 182 | BitWriter_Open(&stream, buffer, file_size); 183 | for (i = 0; i < file_size; i++) { 184 | StaticHuffman_PutCode(&codes, &stream, data[i]); 185 | } 186 | BitStream_Flush(&stream); 187 | 188 | BitStream_Tell(&stream, (int32_t *)&output_size); 189 | 190 | /* 符号取得/一致確認 */ 191 | BitReader_Open(&stream, buffer, output_size); 192 | for (i = 0; i < file_size; i++) { 193 | const uint32_t test = StaticHuffman_GetCode(&tree, &stream); 194 | EXPECT_EQ(data[i], test); 195 | } 196 | 197 | free(data); 198 | free(buffer); 199 | #undef FILENAME 200 | } 201 | } 202 | 203 | int main(int argc, char **argv) 204 | { 205 | ::testing::InitGoogleTest(&argc, argv); 206 | return RUN_ALL_TESTS(); 207 | } 208 | -------------------------------------------------------------------------------- /test/static_huffman/test.txt: -------------------------------------------------------------------------------- 1 | ついにスターライトクイーンカップのけっしょうがやってきた!美月が三年れんぞくトップになるのか、だれかがそのざをうばうのか…!そしていちごは、あるおどろきのけっ心をみんなにつげる。 2 | -------------------------------------------------------------------------------- /test/wav/16bit.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/test/wav/16bit.wav -------------------------------------------------------------------------------- /test/wav/16bit_2ch.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/test/wav/16bit_2ch.wav -------------------------------------------------------------------------------- /test/wav/24bit.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/test/wav/24bit.wav -------------------------------------------------------------------------------- /test/wav/24bit_2ch.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/test/wav/24bit_2ch.wav -------------------------------------------------------------------------------- /test/wav/32bit.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/test/wav/32bit.wav -------------------------------------------------------------------------------- /test/wav/32bit_2ch.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/test/wav/32bit_2ch.wav -------------------------------------------------------------------------------- /test/wav/8bit.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/test/wav/8bit.wav -------------------------------------------------------------------------------- /test/wav/8bit_2ch.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/test/wav/8bit_2ch.wav -------------------------------------------------------------------------------- /test/wav/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # テスト名 6 | set(TEST_NAME wav_test) 7 | 8 | # 実行形式ファイル 9 | add_executable(${TEST_NAME} main.cpp) 10 | 11 | # インクルードディレクトリ 12 | include_directories(${PROJECT_ROOT_PATH}/libs/wav/include) 13 | 14 | # リンクするライブラリ 15 | target_link_libraries(${TEST_NAME} gtest gtest_main) 16 | if (NOT MSVC) 17 | target_link_libraries(${TEST_NAME} pthread) 18 | endif() 19 | 20 | # コンパイルオプション 21 | set_target_properties(${TEST_NAME} 22 | PROPERTIES 23 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 24 | ) 25 | 26 | # 実行パスをtmp以下に 27 | add_test( 28 | NAME wav 29 | WORKING_DIRECTORY $/tmp 30 | COMMAND $ 31 | ) 32 | 33 | # run with: ctest -L lib 34 | set_property( 35 | TEST wav 36 | PROPERTY LABELS lib wav 37 | ) 38 | 39 | # ビルド後にテストリソースを持ってくる 40 | file(GLOB TEST_WAVE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.wav) 41 | add_custom_command( 42 | TARGET ${TEST_NAME} 43 | POST_BUILD 44 | COMMAND ${CMAKE_COMMAND} -E make_directory $/tmp 45 | COMMAND ${CMAKE_COMMAND} -E copy ${TEST_WAVE_FILES} $/tmp 46 | ) 47 | -------------------------------------------------------------------------------- /test/wav/a.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sound-Linux-More/srla/7a2e384ec78b7da6ff5d439c4b7667aaa72393f5/test/wav/a.wav -------------------------------------------------------------------------------- /test/wav/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | /* テスト対象のモジュール */ 7 | extern "C" { 8 | #include "../../libs/wav/src/wav.c" 9 | } 10 | 11 | /* WAVファイルフォーマット取得テスト */ 12 | TEST(WAVTest, GetWAVFormatTest) 13 | { 14 | 15 | /* 失敗テスト */ 16 | { 17 | struct WAVFileFormat format; 18 | 19 | EXPECT_EQ( 20 | WAV_APIRESULT_NG, 21 | WAV_GetWAVFormatFromFile(NULL, &format)); 22 | EXPECT_EQ( 23 | WAV_APIRESULT_NG, 24 | WAV_GetWAVFormatFromFile("a.wav", NULL)); 25 | EXPECT_EQ( 26 | WAV_APIRESULT_NG, 27 | WAV_GetWAVFormatFromFile(NULL, NULL)); 28 | 29 | /* 存在しないファイルを開こうとして失敗するか? */ 30 | EXPECT_EQ( 31 | WAV_APIRESULT_NG, 32 | WAV_GetWAVFormatFromFile("dummy.a.wav.wav", &format)); 33 | } 34 | 35 | /* 実wavファイルからの取得テスト */ 36 | { 37 | struct WAVFileFormat format; 38 | EXPECT_EQ( 39 | WAV_APIRESULT_OK, 40 | WAV_GetWAVFormatFromFile("a.wav", &format)); 41 | } 42 | 43 | } 44 | 45 | /* WAVファイルデータ取得テスト */ 46 | TEST(WAVTest, CreateDestroyTest) 47 | { 48 | 49 | /* 失敗テスト */ 50 | { 51 | struct WAVFileFormat format; 52 | format.data_format = (WAVDataFormat)255; /* 不正なフォーマット */ 53 | format.bits_per_sample = 16; 54 | format.num_channels = 8; 55 | format.sampling_rate = 48000; 56 | format.num_samples = 48000 * 5; 57 | EXPECT_TRUE(WAV_Create(NULL) == NULL); 58 | EXPECT_TRUE(WAV_Create(&format) == NULL); 59 | EXPECT_TRUE(WAV_CreateFromFile(NULL) == NULL); 60 | EXPECT_TRUE(WAV_CreateFromFile("dummy.a.wav.wav") == NULL); 61 | } 62 | 63 | /* ハンドル作成 / 破棄テスト */ 64 | { 65 | uint32_t ch, is_ok; 66 | struct WAVFile* wavfile; 67 | struct WAVFileFormat format; 68 | format.data_format = WAV_DATA_FORMAT_PCM; 69 | format.bits_per_sample = 16; 70 | format.num_channels = 8; 71 | format.sampling_rate = 48000; 72 | format.num_samples = 48000 * 5; 73 | 74 | wavfile = WAV_Create(&format); 75 | EXPECT_TRUE(wavfile != NULL); 76 | EXPECT_TRUE(wavfile->data != NULL); 77 | EXPECT_EQ( 78 | 0, 79 | memcmp(&wavfile->format, &format, sizeof(struct WAVFileFormat))); 80 | is_ok = 1; 81 | for (ch = 0; ch < wavfile->format.num_channels; ch++) { 82 | if (wavfile->data[ch] == NULL) { 83 | is_ok = 0; 84 | break; 85 | } 86 | } 87 | EXPECT_EQ(1, is_ok); 88 | 89 | WAV_Destroy(wavfile); 90 | } 91 | 92 | 93 | /* 実wavファイルからの取得テスト */ 94 | { 95 | struct WAVFile* wavfile; 96 | 97 | wavfile = WAV_CreateFromFile("a.wav"); 98 | EXPECT_TRUE(wavfile != NULL); 99 | WAV_Destroy(wavfile); 100 | } 101 | } 102 | 103 | /* WAVファイルデータ書き込みテスト */ 104 | TEST(WAVTest, WriteTest) 105 | { 106 | /* 失敗テスト */ 107 | { 108 | const char test_filename[] = "test.wav"; 109 | struct WAVWriter writer; 110 | struct WAVFileFormat format; 111 | FILE *fp; 112 | 113 | format.data_format = (WAVDataFormat)0xFF; /* 不正 */ 114 | format.num_samples = 0; /* dummy */ 115 | format.num_channels = 0; /* dummy */ 116 | format.bits_per_sample = 0; /* dummy */ 117 | format.sampling_rate = 0; /* dummy */ 118 | 119 | fp = fopen(test_filename, "wb"); 120 | WAVWriter_Initialize(&writer, fp); 121 | 122 | EXPECT_NE( 123 | WAV_ERROR_OK, 124 | WAVWriter_PutWAVHeader(&writer, NULL)); 125 | EXPECT_NE( 126 | WAV_ERROR_OK, 127 | WAVWriter_PutWAVHeader(NULL, &format)); 128 | EXPECT_NE( 129 | WAV_ERROR_OK, 130 | WAVWriter_PutWAVHeader(NULL, NULL)); 131 | EXPECT_NE( 132 | WAV_ERROR_OK, 133 | WAVWriter_PutWAVHeader(&writer, &format)); 134 | 135 | WAVWriter_Finalize(&writer); 136 | fclose(fp); 137 | } 138 | 139 | /* PCMデータ書き出しテスト */ 140 | { 141 | const char test_filename[] = "test.wav"; 142 | struct WAVWriter writer; 143 | struct WAVFileFormat format; 144 | FILE *fp; 145 | struct WAVFile* wavfile; 146 | uint32_t ch, sample; 147 | 148 | /* 適宜フォーマットを用意 */ 149 | format.data_format = WAV_DATA_FORMAT_PCM; 150 | format.num_samples = 16; 151 | format.num_channels = 1; 152 | format.sampling_rate = 48000; 153 | format.bits_per_sample = 8; 154 | 155 | /* ハンドル作成 */ 156 | wavfile = WAV_Create(&format); 157 | EXPECT_TRUE(wavfile != NULL); 158 | 159 | /* データを書いてみる */ 160 | for (ch = 0; ch < format.num_channels; ch++) { 161 | for (sample = 0; sample < format.num_samples; sample++) { 162 | WAVFile_PCM(wavfile, sample, ch) = sample - (int32_t)format.num_samples / 2; 163 | } 164 | } 165 | 166 | fp = fopen(test_filename, "wb"); 167 | WAVWriter_Initialize(&writer, fp); 168 | 169 | /* 不正なビット深度に書き換えて書き出し */ 170 | /* -> 失敗を期待 */ 171 | wavfile->format.bits_per_sample = 3; 172 | EXPECT_NE( 173 | WAV_ERROR_OK, 174 | WAVWriter_PutWAVPcmData(&writer, wavfile)); 175 | 176 | /* 書き出し */ 177 | wavfile->format.bits_per_sample = 8; 178 | EXPECT_EQ( 179 | WAV_ERROR_OK, 180 | WAVWriter_PutWAVPcmData(&writer, wavfile)); 181 | 182 | WAVWriter_Finalize(&writer); 183 | fclose(fp); 184 | } 185 | 186 | /* 実ファイルを読み出してそのまま書き出してみる */ 187 | { 188 | uint32_t ch, is_ok, i_test; 189 | const char* test_sourcefile_list[] = { 190 | "a.wav", 191 | "8bit.wav", 192 | "16bit.wav", 193 | "24bit.wav", 194 | "32bit.wav", 195 | "8bit_2ch.wav", 196 | "16bit_2ch.wav", 197 | "24bit_2ch.wav", 198 | "32bit_2ch.wav", 199 | }; 200 | const char test_filename[] = "tmp.wav"; 201 | struct WAVFile *src_wavfile, *test_wavfile; 202 | WAVApiResult ret; 203 | 204 | for (i_test = 0; 205 | i_test < sizeof(test_sourcefile_list) / sizeof(test_sourcefile_list[0]); 206 | i_test++) { 207 | /* 元になるファイルを読み込み */ 208 | src_wavfile = WAV_CreateFromFile(test_sourcefile_list[i_test]); 209 | 210 | /* 読み込んだデータをそのままファイルへ書き出し */ 211 | ret = WAV_WriteToFile(test_filename, src_wavfile); 212 | ASSERT_EQ(WAV_APIRESULT_OK, ret); 213 | 214 | /* 一度書き出したファイルを読み込んでみる */ 215 | test_wavfile = WAV_CreateFromFile(test_filename); 216 | ASSERT_TRUE(test_wavfile != NULL); 217 | 218 | /* 最初に読み込んだファイルと一致するか? */ 219 | /* フォーマットの一致確認 */ 220 | EXPECT_EQ( 221 | 0, memcmp(&src_wavfile->format, &test_wavfile->format, sizeof(struct WAVFileFormat))); 222 | 223 | /* PCMの一致確認 */ 224 | is_ok = 1; 225 | for (ch = 0; ch < src_wavfile->format.num_channels; ch++) { 226 | if (memcmp(src_wavfile->data[ch], test_wavfile->data[ch], 227 | sizeof(WAVPcmData) * src_wavfile->format.num_samples) != 0) { 228 | is_ok = 0; 229 | break; 230 | } 231 | } 232 | EXPECT_EQ(1, is_ok); 233 | 234 | /* ハンドル破棄 */ 235 | WAV_Destroy(src_wavfile); 236 | WAV_Destroy(test_wavfile); 237 | } 238 | } 239 | 240 | } 241 | 242 | int main(int argc, char **argv) 243 | { 244 | ::testing::InitGoogleTest(&argc, argv); 245 | return RUN_ALL_TESTS(); 246 | } 247 | -------------------------------------------------------------------------------- /tools/srla_codec/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # プロジェクト名 6 | project(SRLACodec C) 7 | 8 | # アプリケーション名 9 | set(APP_NAME srla) 10 | 11 | # ライブラリのテストはしない 12 | set(without-test 1) 13 | 14 | # 実行形式ファイル 15 | add_executable(${APP_NAME} srla_codec.c) 16 | 17 | # 依存するサブディレクトリを追加 18 | add_subdirectory(${PROJECT_ROOT_PATH} ${CMAKE_CURRENT_BINARY_DIR}/libsrlacodec) 19 | 20 | # インクルードパス 21 | target_include_directories(${APP_NAME} 22 | PRIVATE 23 | ${PROJECT_ROOT_PATH}/include 24 | ) 25 | 26 | # リンクするライブラリ 27 | target_link_libraries(${APP_NAME} command_line_parser) 28 | target_link_libraries(${APP_NAME} wav) 29 | target_link_libraries(${APP_NAME} srlacodec) 30 | if (UNIX AND NOT APPLE) 31 | target_link_libraries(${APP_NAME} m) 32 | endif() 33 | 34 | # コンパイルオプション 35 | if(MSVC) 36 | target_compile_options(${APP_NAME} PRIVATE /W4) 37 | set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Oi /Ot /Oy /GL") 38 | set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG") 39 | else() 40 | target_compile_options(${APP_NAME} PRIVATE -Wall -Wextra -Wpedantic -Wformat=2 -Wstrict-aliasing=2 -Wconversion -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition) 41 | set(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -DDEBUG") 42 | set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") 43 | endif() 44 | set_target_properties(${APP_NAME} 45 | PROPERTIES 46 | C_STANDARD 90 C_EXTENSIONS OFF 47 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 48 | ) 49 | -------------------------------------------------------------------------------- /tools/srla_player/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(PROJECT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) 4 | 5 | # プロジェクト名 6 | project(SRLAPlayer C) 7 | 8 | # アプリケーション名 9 | set(APP_NAME srlaplayer) 10 | 11 | # ライブラリのテストはしない 12 | set(without-test 1) 13 | 14 | # 実行形式ファイル 15 | add_executable(${APP_NAME} srla_player.c) 16 | 17 | # 依存するサブディレクトリを追加 18 | add_subdirectory(${PROJECT_ROOT_PATH} ${CMAKE_CURRENT_BINARY_DIR}/libsrladec) 19 | 20 | # 機種依存のソース追加 21 | if (APPLE) 22 | set(CMAKE_C_FLAGS "-framework Audiotoolbox -framework CoreAudio -framework CoreServices") 23 | target_sources(${APP_NAME} PRIVATE srla_player_coreaudio.c) 24 | elseif (MSVC) 25 | target_sources(${APP_NAME} PRIVATE srla_player_wasapi.c) 26 | elseif (UNIX) 27 | target_sources(${APP_NAME} PRIVATE srla_player_pulseaudio.c) 28 | endif() 29 | 30 | # インクルードパス 31 | target_include_directories(${APP_NAME} 32 | PRIVATE 33 | ${PROJECT_ROOT_PATH}/include 34 | ) 35 | 36 | # リンクするライブラリ 37 | target_link_libraries(${APP_NAME} srladec) 38 | if (UNIX AND NOT APPLE) 39 | target_link_libraries(${APP_NAME} pulse-simple pulse m) 40 | endif() 41 | 42 | # コンパイルオプション 43 | if(MSVC) 44 | target_compile_options(${APP_NAME} PRIVATE /W4) 45 | set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Oi /Ot /Oy /GL") 46 | set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG") 47 | else() 48 | target_compile_options(${APP_NAME} PRIVATE -Wall -Wextra -Wpedantic -Wformat=2 -Wstrict-aliasing=2 -Wconversion -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition) 49 | set(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -DDEBUG") 50 | set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") 51 | endif() 52 | set_target_properties(${APP_NAME} 53 | PROPERTIES 54 | C_STANDARD 90 C_EXTENSIONS OFF 55 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" 56 | ) 57 | -------------------------------------------------------------------------------- /tools/srla_player/srla_player.c: -------------------------------------------------------------------------------- 1 | #include "srla_player.h" 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* 出力要求コールバック */ 10 | static void SRLAPlayer_SampleRequestCallback(int32_t **buffer, uint32_t num_channels, uint32_t num_samples); 11 | /* 終了処理 */ 12 | static void exit_srla_player(void); 13 | 14 | /* 再生制御のためのグローバル変数 */ 15 | static struct SRLAHeader header = { 0, }; 16 | static uint32_t output_samples = 0; 17 | static int32_t *decode_buffer[SRLA_MAX_NUM_CHANNELS] = { NULL, }; 18 | static uint32_t num_buffered_samples = 0; 19 | static uint32_t buffer_pos = 0; 20 | static uint32_t data_size = 0; 21 | static uint8_t *data = NULL; 22 | static uint32_t decode_offset = 0; 23 | static struct SRLADecoder* decoder = NULL; 24 | 25 | /* メインエントリ */ 26 | int main(int argc, char **argv) 27 | { 28 | uint32_t i; 29 | SRLAApiResult ret; 30 | struct SRLADecoderConfig decoder_config; 31 | struct SRLAPlayerConfig player_config; 32 | 33 | /* 引数チェック 間違えたら使用方法を提示 */ 34 | if (argc != 2) { 35 | printf("Usage: %s SRLAFILE \n", argv[0]); 36 | return 1; 37 | } 38 | 39 | /* lnnファイルのロード */ 40 | { 41 | struct stat fstat; 42 | FILE* fp; 43 | const char *filename = argv[1]; 44 | 45 | /* ファイルオープン */ 46 | if ((fp = fopen(filename, "rb")) == NULL) { 47 | fprintf(stderr, "Failed to open %s \n", filename); 48 | return 1; 49 | } 50 | 51 | /* 入力ファイルのサイズ取得 / バッファ領域割り当て */ 52 | stat(filename, &fstat); 53 | data_size = (uint32_t)fstat.st_size; 54 | data = (uint8_t *)malloc(data_size); 55 | 56 | /* バッファ領域にデータをロード */ 57 | if (fread(data, sizeof(uint8_t), data_size, fp) < data_size) { 58 | fprintf(stderr, "Failed to load %s data \n", filename); 59 | return 1; 60 | } 61 | 62 | fclose(fp); 63 | } 64 | 65 | /* ヘッダデコード */ 66 | if ((ret = SRLADecoder_DecodeHeader(data, data_size, &header)) != SRLA_APIRESULT_OK) { 67 | fprintf(stderr, "Failed to get header information: %d \n", ret); 68 | return 1; 69 | } 70 | 71 | /* デコーダハンドルの作成 */ 72 | decoder_config.max_num_channels = header.num_channels; 73 | decoder_config.max_num_parameters = SRLA_MAX_COEFFICIENT_ORDER; 74 | decoder_config.check_checksum = 1; 75 | if ((decoder = SRLADecoder_Create(&decoder_config, NULL, 0)) == NULL) { 76 | fprintf(stderr, "Failed to create decoder handle. \n"); 77 | return 1; 78 | } 79 | 80 | /* デコーダにヘッダをセット */ 81 | if ((ret = SRLADecoder_SetHeader(decoder, &header)) != SRLA_APIRESULT_OK) { 82 | fprintf(stderr, "Failed to set header to decoder. \n"); 83 | return 1; 84 | } 85 | 86 | /* デコード出力領域割当 */ 87 | for (i = 0; i < header.num_channels; i++) { 88 | decode_buffer[i] = (int32_t *)malloc(sizeof(int32_t) * header.max_num_samples_per_block); 89 | memset(decode_buffer[i], 0, sizeof(int32_t) * header.max_num_samples_per_block); 90 | } 91 | 92 | /* デコード位置をヘッダ分進める */ 93 | decode_offset = SRLA_HEADER_SIZE; 94 | 95 | /* プレイヤー初期化 */ 96 | player_config.sampling_rate = header.sampling_rate; 97 | player_config.num_channels = header.num_channels; 98 | player_config.bits_per_sample = header.bits_per_sample; 99 | player_config.sample_request_callback = SRLAPlayer_SampleRequestCallback; 100 | SRLAPlayer_Initialize(&player_config); 101 | 102 | /* この後はコールバック要求により進む */ 103 | while (1) { ; } 104 | 105 | return 0; 106 | } 107 | 108 | /* 出力要求コールバック */ 109 | static void SRLAPlayer_SampleRequestCallback(int32_t **buffer, uint32_t num_channels, uint32_t num_samples) 110 | { 111 | uint32_t ch, smpl; 112 | 113 | for (smpl = 0; smpl < num_samples; smpl++) { 114 | /* バッファを使い切ったら即時にデコード */ 115 | if (buffer_pos >= num_buffered_samples) { 116 | uint32_t decode_size; 117 | if (SRLADecoder_DecodeBlock(decoder, 118 | &data[decode_offset], data_size - decode_offset, 119 | decode_buffer, header.num_channels, header.max_num_samples_per_block, 120 | &decode_size, &num_buffered_samples) != SRLA_APIRESULT_OK) { 121 | fprintf(stderr, "decoding error! \n"); 122 | exit(1); 123 | } 124 | buffer_pos = 0; 125 | decode_offset += decode_size; 126 | } 127 | 128 | /* 出力用バッファ領域にコピー */ 129 | for (ch = 0; ch < num_channels; ch++) { 130 | buffer[ch][smpl] = decode_buffer[ch][buffer_pos]; 131 | } 132 | buffer_pos++; 133 | output_samples++; 134 | 135 | /* 再生終了次第終了処理へ */ 136 | if (output_samples >= header.num_samples) { 137 | exit_srla_player(); 138 | } 139 | } 140 | 141 | /* 進捗表示 */ 142 | printf("playing... %7.3f / %7.3f \r", 143 | (double)output_samples / header.sampling_rate, (double)header.num_samples / header.sampling_rate); 144 | fflush(stdout); 145 | } 146 | 147 | /* 終了処理 */ 148 | static void exit_srla_player(void) 149 | { 150 | uint32_t i; 151 | 152 | SRLAPlayer_Finalize(); 153 | 154 | for (i = 0; i < header.num_channels; i++) { 155 | free(decode_buffer[i]); 156 | } 157 | SRLADecoder_Destroy(decoder); 158 | free(data); 159 | 160 | exit(0); 161 | } 162 | -------------------------------------------------------------------------------- /tools/srla_player/srla_player.h: -------------------------------------------------------------------------------- 1 | #ifndef SRLAPLAYER_H_INCLUDED 2 | #define SRLAPLAYER_H_INCLUDED 3 | 4 | #include 5 | 6 | /* 出力要求コールバック */ 7 | typedef void (*SRLASampleRequestCallback)( 8 | int32_t **buffer, uint32_t num_channels, uint32_t num_samples); 9 | 10 | /* プレイヤー初期化コンフィグ */ 11 | struct SRLAPlayerConfig { 12 | uint32_t sampling_rate; 13 | uint16_t num_channels; 14 | uint16_t bits_per_sample; 15 | SRLASampleRequestCallback sample_request_callback; 16 | }; 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | /* 初期化 この関数内でデバイスドライバの初期化を行い、再生開始 */ 23 | void SRLAPlayer_Initialize(const struct SRLAPlayerConfig *config); 24 | 25 | /* 終了 初期化したときのリソースの開放はここで */ 26 | void SRLAPlayer_Finalize(void); 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | #endif /* SRLAPLAYER_H_INCLUDED */ 33 | -------------------------------------------------------------------------------- /tools/srla_player/srla_player_coreaudio.c: -------------------------------------------------------------------------------- 1 | #include "srla_player.h" 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define NUM_BUFFERS 3 9 | #define BUFFER_SIZE (8 * 1024) 10 | #define DECODE_BUFFER_NUM_SAMPLES (1024) 11 | 12 | /* CoreAudioの出力コールバック関数 */ 13 | static void SRLAPlayer_CoreAudioCallback(void *custom_data, AudioQueueRef queue, AudioQueueBufferRef buffer); 14 | 15 | /* 初期化カウント */ 16 | static int32_t st_initialize_count = 0; 17 | /* 初期化時のプレイヤーコンフィグ */ 18 | static struct SRLAPlayerConfig st_config = { 0, }; 19 | /* デコードしたデータのバッファ領域 */ 20 | static int32_t **st_decode_buffer = NULL; 21 | /* バッファ参照位置 */ 22 | static uint32_t st_buffer_pos = DECODE_BUFFER_NUM_SAMPLES; /* 空の状態 */ 23 | /* 出力キューの参照 */ 24 | static AudioQueueRef queue = NULL; 25 | 26 | /* 初期化 この関数内でデバイスドライバの初期化を行い、再生開始 */ 27 | void SRLAPlayer_Initialize(const struct SRLAPlayerConfig *config) 28 | { 29 | uint32_t i; 30 | AudioStreamBasicDescription format; 31 | AudioQueueBufferRef buffers[NUM_BUFFERS]; 32 | 33 | assert(config != NULL); 34 | 35 | /* 多重初期化は不可 */ 36 | if (st_initialize_count > 0) { 37 | return; 38 | } 39 | 40 | /* コンフィグ取得 */ 41 | st_config = (*config); 42 | 43 | /* フォーマットに属性を詰める */ 44 | format.mSampleRate = st_config.sampling_rate; /* サンプリングレート */ 45 | format.mFormatID = kAudioFormatLinearPCM; /* フォーマット: PCM */ 46 | format.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; /* フォーマットフラグの指定. */ 47 | format.mBitsPerChannel = st_config.bits_per_sample; /* チャンネル当たりのビット数 */ 48 | format.mChannelsPerFrame = st_config.num_channels; /* チャンネル数 */ 49 | format.mBytesPerFrame = (st_config.bits_per_sample * st_config.num_channels) / 8; /* 1フレーム(全てのフレームの1サンプル)のバイト数 */ 50 | format.mFramesPerPacket = 1; /* パケットあたりのフレーム数 */ 51 | format.mBytesPerPacket = format.mBytesPerFrame * format.mFramesPerPacket; /* パケット当たりのバイト数 */ 52 | format.mReserved = 0; /* (予約領域) */ 53 | 54 | /* デコード領域のバッファ確保 */ 55 | st_decode_buffer = (int32_t **)malloc(sizeof(int32_t *) * st_config.num_channels); 56 | for (i = 0; i < st_config.num_channels; i++) { 57 | st_decode_buffer[i] = (int32_t *)malloc(sizeof(int32_t) * DECODE_BUFFER_NUM_SAMPLES); 58 | memset(st_decode_buffer[i], 0, sizeof(int32_t) * DECODE_BUFFER_NUM_SAMPLES); 59 | } 60 | 61 | /* 新しい出力キューを生成 */ 62 | AudioQueueNewOutput(&format, 63 | SRLAPlayer_CoreAudioCallback, NULL, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &queue); 64 | 65 | for (i = 0; i < NUM_BUFFERS; i++) { 66 | /* 指定したキューのバッファの領域を割り当てる */ 67 | AudioQueueAllocateBuffer(queue, BUFFER_SIZE, &buffers[i]); 68 | /* サイズをセット */ 69 | buffers[i]->mAudioDataByteSize = BUFFER_SIZE; 70 | /* 一発目のデータを出力 */ 71 | SRLAPlayer_CoreAudioCallback(NULL, queue, buffers[i]); 72 | } 73 | 74 | /* キューの再生開始 */ 75 | AudioQueueStart(queue, NULL); 76 | 77 | /* スレッドのループ処理開始 78 | * この関数が終わってもスレッド処理が回る(監視ループというらしい) */ 79 | CFRunLoopRun(); 80 | 81 | st_initialize_count++; 82 | } 83 | 84 | /* 終了 初期化したときのリソースの開放はここで */ 85 | void SRLAPlayer_Finalize(void) 86 | { 87 | if (st_initialize_count == 1) { 88 | uint32_t i; 89 | /* キューの停止・破棄 */ 90 | AudioQueueStop(queue, false); 91 | AudioQueueDispose(queue, false); 92 | CFRunLoopStop(CFRunLoopGetCurrent()); 93 | 94 | /* デコード領域のバッファ開放 */ 95 | for (i = 0; i < st_config.num_channels; i++) { 96 | free(st_decode_buffer[i]); 97 | } 98 | free(st_decode_buffer); 99 | } 100 | 101 | st_initialize_count--; 102 | } 103 | 104 | /* CoreAudioの出力コールバック関数 */ 105 | static void SRLAPlayer_CoreAudioCallback(void *custom_data, AudioQueueRef queue, AudioQueueBufferRef buffer) 106 | { 107 | uint32_t i, ch; 108 | int16_t *ch_interleaved_buffer = (int16_t *)buffer->mAudioData; 109 | const uint32_t num_buffer_samples = BUFFER_SIZE / sizeof(int16_t); 110 | 111 | for (i = 0; i < num_buffer_samples; i += st_config.num_channels) { 112 | /* バッファを使い切っていたらその場で次のデータを要求 */ 113 | if (st_buffer_pos >= DECODE_BUFFER_NUM_SAMPLES) { 114 | st_config.sample_request_callback(st_decode_buffer, st_config.num_channels, DECODE_BUFFER_NUM_SAMPLES); 115 | st_buffer_pos = 0; 116 | } 117 | 118 | /* インターリーブしたバッファにデータを詰める */ 119 | for (ch = 0; ch < st_config.num_channels; ch++) { 120 | ch_interleaved_buffer[i + ch] = (int16_t)st_decode_buffer[ch][st_buffer_pos]; 121 | } 122 | st_buffer_pos++; 123 | } 124 | 125 | /* バッファをエンキュー */ 126 | AudioQueueEnqueueBuffer(queue, buffer, 0, NULL); 127 | } 128 | -------------------------------------------------------------------------------- /tools/srla_player/srla_player_pulseaudio.c: -------------------------------------------------------------------------------- 1 | #include "srla_player.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* C89環境でビルドするためinlineキーワードを無効にする */ 8 | #define inline 9 | #include 10 | #include 11 | #include 12 | 13 | #define BUFFER_SIZE (1 * 1024) 14 | #define DECODE_BUFFER_NUM_SAMPLES (1024) 15 | 16 | /* 初期化カウント */ 17 | static int32_t st_initialize_count = 0; 18 | /* 初期化時のプレイヤーコンフィグ */ 19 | static struct SRLAPlayerConfig st_config = { 0, }; 20 | /* デコードしたデータのバッファ領域 */ 21 | static int32_t **st_decode_buffer = NULL; 22 | /* バッファ参照位置 */ 23 | static uint32_t st_buffer_pos = DECODE_BUFFER_NUM_SAMPLES; /* 空の状態 */ 24 | /* simple pulseaudio ハンドル */ 25 | static pa_simple *pa_simple_hn = NULL; 26 | /* バッファ領域 */ 27 | static uint8_t buffer[BUFFER_SIZE]; 28 | 29 | /* 初期化 この関数内でデバイスドライバの初期化を行い、再生開始 */ 30 | void SRLAPlayer_Initialize(const struct SRLAPlayerConfig *config) 31 | { 32 | uint32_t i; 33 | int error; 34 | pa_sample_spec sample_spec; 35 | 36 | assert(config != NULL); 37 | 38 | /* 多重初期化は不可 */ 39 | if (st_initialize_count > 0) { 40 | return; 41 | } 42 | 43 | /* コンフィグ取得 */ 44 | st_config = (*config); 45 | 46 | /* フォーマットに属性を詰める */ 47 | sample_spec.format = PA_SAMPLE_S16LE; 48 | sample_spec.rate = st_config.sampling_rate; 49 | sample_spec.channels = (uint8_t)st_config.num_channels; 50 | 51 | /* デコード領域のバッファ確保 */ 52 | st_decode_buffer = (int32_t **)malloc(sizeof(int32_t *) * st_config.num_channels); 53 | for (i = 0; i < st_config.num_channels; i++) { 54 | st_decode_buffer[i] = (int32_t *)malloc(sizeof(int32_t) * DECODE_BUFFER_NUM_SAMPLES); 55 | memset(st_decode_buffer[i], 0, sizeof(int32_t) * DECODE_BUFFER_NUM_SAMPLES); 56 | } 57 | 58 | /* playbackハンドル作成 */ 59 | if ((pa_simple_hn = pa_simple_new(NULL, "SRLAPlayer", PA_STREAM_PLAYBACK, NULL, "playback", 60 | &sample_spec, NULL, NULL, &error)) == NULL) { 61 | fprintf(stderr, "failed to create pulseaudio playback: %s \n", pa_strerror(error)); 62 | exit(1); 63 | } 64 | 65 | st_initialize_count++; 66 | 67 | while (1) { 68 | uint32_t i, ch; 69 | int16_t *pbuffer = (int16_t *)&buffer[0]; 70 | const uint32_t num_writable_samples_per_channel = (uint32_t)(BUFFER_SIZE / (st_config.num_channels * sizeof(int16_t))); 71 | 72 | for (i = 0; i < num_writable_samples_per_channel; i++) { 73 | /* バッファを使い切っていたらその場で次のデータを要求 */ 74 | if (st_buffer_pos >= DECODE_BUFFER_NUM_SAMPLES) { 75 | st_config.sample_request_callback(st_decode_buffer, st_config.num_channels, DECODE_BUFFER_NUM_SAMPLES); 76 | st_buffer_pos = 0; 77 | } 78 | /* インターリーブしたバッファにデータを詰める */ 79 | for (ch = 0; ch < st_config.num_channels; ch++) { 80 | *pbuffer++ = (int16_t)st_decode_buffer[ch][st_buffer_pos]; 81 | } 82 | st_buffer_pos++; 83 | } 84 | 85 | if (pa_simple_write(pa_simple_hn, buffer, BUFFER_SIZE, &error) < 0) { 86 | fprintf(stderr, "pa_simple_write() failed: %s\n", pa_strerror(error)); 87 | exit(1); 88 | } 89 | } 90 | } 91 | 92 | /* 終了 初期化したときのリソースの開放はここで */ 93 | void SRLAPlayer_Finalize(void) 94 | { 95 | if (st_initialize_count == 1) { 96 | uint32_t i; 97 | 98 | pa_simple_free(pa_simple_hn); 99 | 100 | /* デコード領域のバッファ開放 */ 101 | for (i = 0; i < st_config.num_channels; i++) { 102 | free(st_decode_buffer[i]); 103 | } 104 | free(st_decode_buffer); 105 | } 106 | 107 | st_initialize_count--; 108 | } 109 | -------------------------------------------------------------------------------- /tools/srla_player/srla_player_wasapi.c: -------------------------------------------------------------------------------- 1 | #include "srla_player.h" 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | /* マクロ呼び出しを使うためCOBJMACROSを定義 */ 8 | #define COBJMACROS 9 | #include 10 | #include 11 | #undef COBJMACROS 12 | 13 | #define DECODE_BUFFER_NUM_SAMPLES (1024) 14 | #define REQUESTED_SOUND_BUFFER_DURATION (2 * 10000000LL) /* 内部に要求するバッファサイズ[100ナノ秒] */ 15 | 16 | /* 初期化カウント */ 17 | static int32_t st_initialize_count = 0; 18 | /* 初期化時のプレイヤーコンフィグ */ 19 | static struct SRLAPlayerConfig st_config = { 0, }; 20 | /* デコードしたデータのバッファ領域 */ 21 | static int32_t** st_decode_buffer = NULL; 22 | /* バッファ参照位置 */ 23 | static uint32_t st_buffer_pos = DECODE_BUFFER_NUM_SAMPLES; /* 空の状態 */ 24 | /* WASAPI制御用のハンドル */ 25 | static IAudioClient* audio_client = NULL; 26 | static IAudioRenderClient* audio_render_client = NULL; 27 | 28 | /* CLSID,IIDを自前定義 */ 29 | /* 補足)C++ソースにしないと__uuidが使えない。C++にするならクラスを使う。しかしwindowsの事情だけで全てをC++プロジェクトにしたくない */ 30 | static const CLSID st_CLSID_MMDeviceEnumerator = { 0xBCDE0395, 0xE52F, 0x467C, {0x8E,0x3D,0xC4,0x57,0x92,0x91,0x69,0x2E} }; 31 | static const IID st_IID_IMMDeviceEnumerator = { 0xA95664D2, 0x9614, 0x4F35, {0xA7,0x46,0xDE,0x8D,0xB6,0x36,0x17,0xE6} }; 32 | static const IID st_IID_IAudioClient = { 0x1CB9AD4C, 0xDBFA, 0x4C32, {0xB1,0x78,0xC2,0xF5,0x68,0xA7,0x03,0xB2} }; 33 | static const IID st_IID_IAudioClockAdjustment = { 0xF6E4C0A0, 0x46D9, 0x4FB8, {0xBE,0x21,0x57,0xA3,0xEF,0x2B,0x62,0x6C} }; 34 | static const IID st_IID_IAudioRenderClient = { 0xF294ACFC, 0x3146, 0x4483, {0xA7,0xBF,0xAD,0xDC,0xA7,0xC2,0x60,0xE2} }; 35 | 36 | /* 初期化 この関数内でデバイスドライバの初期化を行い、再生開始 */ 37 | void SRLAPlayer_Initialize(const struct SRLAPlayerConfig* config) 38 | { 39 | uint32_t i, buffer_frame_size; 40 | HRESULT hr; 41 | IMMDeviceEnumerator* device_enumerator; 42 | IMMDevice* audio_device; 43 | WAVEFORMATEX format; 44 | 45 | assert(config != NULL); 46 | 47 | /* 多重初期化は不可 */ 48 | if (st_initialize_count > 0) { 49 | return; 50 | } 51 | 52 | /* コンフィグ取得 */ 53 | st_config = (*config); 54 | 55 | /* デコード領域のバッファ確保 */ 56 | st_decode_buffer = (int32_t**)malloc(sizeof(int32_t*) * st_config.num_channels); 57 | for (i = 0; i < st_config.num_channels; i++) { 58 | st_decode_buffer[i] = (int32_t*)malloc(sizeof(int32_t) * DECODE_BUFFER_NUM_SAMPLES); 59 | memset(st_decode_buffer[i], 0, sizeof(int32_t) * DECODE_BUFFER_NUM_SAMPLES); 60 | } 61 | 62 | /* COMの初期化 */ 63 | hr = CoInitializeEx(NULL, COINIT_SPEED_OVER_MEMORY); 64 | assert(SUCCEEDED(hr)); 65 | 66 | /* マルチメディアデバイス列挙子取得 */ 67 | hr = CoCreateInstance(&st_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &st_IID_IMMDeviceEnumerator, &device_enumerator); 68 | assert(SUCCEEDED(hr)); 69 | 70 | /* デフォルトのデバイス取得 */ 71 | hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(device_enumerator, eRender, eConsole, &audio_device); 72 | assert(SUCCEEDED(hr)); 73 | IMMDeviceEnumerator_Release(device_enumerator); 74 | 75 | /* クライアント取得 */ 76 | hr = IMMDevice_Activate(audio_device, &st_IID_IAudioClient, CLSCTX_ALL, NULL, &audio_client); 77 | assert(SUCCEEDED(hr)); 78 | IMMDevice_Release(audio_device); 79 | 80 | /* 出力フォーマット指定 */ 81 | ZeroMemory(&format, sizeof(WAVEFORMATEX)); 82 | format.wFormatTag = WAVE_FORMAT_PCM; 83 | format.nChannels = st_config.num_channels; 84 | format.nSamplesPerSec = st_config.sampling_rate; 85 | format.wBitsPerSample = st_config.bits_per_sample; 86 | format.nBlockAlign = (format.nChannels * format.wBitsPerSample) / 8; 87 | format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; 88 | 89 | /* 出力フォーマットが対応しているかチェック */ 90 | { 91 | WAVEFORMATEX *pformat; 92 | hr = IAudioClient_IsFormatSupported(audio_client, AUDCLNT_SHAREMODE_SHARED, &format, &pformat); 93 | if (hr != S_OK) { 94 | /* レートは変換できるがそれ以外のフォーマットの差異は対応していないためエラー終了 */ 95 | if ((format.nSamplesPerSec == pformat->nSamplesPerSec) || (format.nChannels != pformat->nChannels)) { 96 | fprintf(stderr, "Unsupported format for WASAPI Playback. \n"); 97 | exit(1); 98 | } 99 | } 100 | } 101 | 102 | /* クライアント初期化 */ 103 | hr = IAudioClient_Initialize(audio_client, 104 | AUDCLNT_SHAREMODE_SHARED, /* 共有モード */ 105 | AUDCLNT_STREAMFLAGS_RATEADJUST /* レート変換を使う(入力波形に合わせたレートで再生する) */ 106 | | AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM /* レート変換の自動挿入を有効にする */ 107 | | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY, /* 良い品質のレート変換を使う */ 108 | REQUESTED_SOUND_BUFFER_DURATION, 0, &format, NULL); 109 | if (FAILED(hr)) { 110 | fprintf(stderr, "Failed to initialize WASAPI client. \n"); 111 | exit(2); 112 | } 113 | 114 | /* サンプリングレート変換設定 */ 115 | { 116 | IAudioClockAdjustment* clock_adj; 117 | hr = IAudioClient_GetService(audio_client, &st_IID_IAudioClockAdjustment, &clock_adj); 118 | assert(SUCCEEDED(hr)); 119 | 120 | hr = IAudioClockAdjustment_SetSampleRate(clock_adj, st_config.sampling_rate); 121 | assert(SUCCEEDED(hr)); 122 | IAudioClockAdjustment_Release(clock_adj); 123 | } 124 | 125 | /* バッファを書き込む為のレンダラーを取得 */ 126 | hr = IAudioClient_GetService(audio_client, &st_IID_IAudioRenderClient, &audio_render_client); 127 | assert(SUCCEEDED(hr)); 128 | 129 | /* 書き込み用のバッファサイズ取得 */ 130 | hr = IAudioClient_GetBufferSize(audio_client, &buffer_frame_size); 131 | assert(SUCCEEDED(hr)); 132 | 133 | /* 再生開始 */ 134 | hr = IAudioClient_Start(audio_client); 135 | assert(SUCCEEDED(hr)); 136 | 137 | st_initialize_count++; 138 | 139 | while (1) { 140 | int16_t* buffer; 141 | /* レイテンシ: 小さすぎると途切れる, 大きすぎると遅延が大きくなる */ 142 | const uint32_t buffer_latency = buffer_frame_size / 50; 143 | uint32_t padding_size, available_buffer_frame_size; 144 | 145 | /* パディングフレームサイズ(サウンドバッファ内に入っていてまだ出力されてないデータ量)の取得 */ 146 | hr = IAudioClient_GetCurrentPadding(audio_client, &padding_size); 147 | assert(SUCCEEDED(hr)); 148 | 149 | /* 書き込み可能なフレームサイズの取得 */ 150 | available_buffer_frame_size = buffer_latency - padding_size; 151 | 152 | /* 書き込み用バッファ取得 */ 153 | hr = IAudioRenderClient_GetBuffer(audio_render_client, available_buffer_frame_size, &buffer); 154 | assert(SUCCEEDED(hr)); 155 | 156 | /* インターリーブしつつ書き込み チャンネル数分のサンプルのまとまりが1フレーム */ 157 | for (i = 0; i < available_buffer_frame_size; i++) { 158 | uint32_t ch; 159 | /* バッファを使い切っていたらその場で次のデータを要求 */ 160 | if (st_buffer_pos >= DECODE_BUFFER_NUM_SAMPLES) { 161 | st_config.sample_request_callback(st_decode_buffer, st_config.num_channels, DECODE_BUFFER_NUM_SAMPLES); 162 | st_buffer_pos = 0; 163 | } 164 | 165 | /* インターリーブしたバッファにデータを詰める */ 166 | for (ch = 0; ch < st_config.num_channels; ch++) { 167 | *buffer++ = (int16_t)st_decode_buffer[ch][st_buffer_pos]; 168 | } 169 | st_buffer_pos++; 170 | } 171 | 172 | /* バッファの解放 */ 173 | hr = IAudioRenderClient_ReleaseBuffer(audio_render_client, available_buffer_frame_size, 0); 174 | assert(SUCCEEDED(hr)); 175 | } 176 | } 177 | 178 | /* 終了 初期化したときのリソースの開放はここで */ 179 | void SRLAPlayer_Finalize(void) 180 | { 181 | if (st_initialize_count == 1) { 182 | IAudioClient_Stop(audio_client); 183 | IAudioClient_Release(audio_client); 184 | IAudioRenderClient_Release(audio_render_client); 185 | } 186 | 187 | st_initialize_count--; 188 | } 189 | --------------------------------------------------------------------------------