diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..8ef33f0 --- /dev/null +++ b/.clang-format @@ -0,0 +1,88 @@ +--- +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: DontAlign +AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: InlineOnly +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: true +BinPackParameters: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Allman +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 100 +CommentPragmas: '^ IWYU pragma:' +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^<[a-z0-9_]+>$' + Priority: 3 + - Regex: '^<(assert|complex|ctype|errno|fenv|float|inttypes|iso646|limits|locale|math|setjmp|signal|stdalign|stdarg|stdatomic|stdbool|stddef|stdint|stdio|stdlib|stdnoreturn|string|tgmath|threads|time|uchar|wchar|wctype)\.h>$' + Priority: 3 + - Regex: '^<' + Priority: 3 + - Regex: '^["<](kodi|p8-platform)\/.*\.h[">]$' + Priority: 2 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '$' +IndentCaseLabels: true +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: None +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60000 +PointerAlignment: Left +ReflowComments: false +SortIncludes: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 8 +UseTab: Never +... diff --git a/.travis.yml b/.travis.yml index 7d9ed74..5860dea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,8 @@ language: cpp # # Define the build matrix # -# Travis defaults to building on Ubuntu Precise when building on -# Linux. We need Trusty in order to get up to date versions of +# Travis defaults to building on Ubuntu Trusty when building on +# Linux. We need Xenial in order to get up to date versions of # cmake and g++. # env: @@ -21,19 +21,33 @@ matrix: dist: xenial sudo: required compiler: clang + - os: linux + dist: bionic + sudo: required + compiler: gcc + env: DEBIAN_BUILD=true - os: osx osx_image: xcode10.2 +before_install: + - if [[ $DEBIAN_BUILD == true ]]; then sudo add-apt-repository -y ppa:team-xbmc/xbmc-nightly; fi + - if [[ $DEBIAN_BUILD == true ]]; then sudo apt-get update; fi + - if [[ $DEBIAN_BUILD == true ]]; then sudo apt-get install fakeroot; fi + # # The addon source is automatically checked out in $TRAVIS_BUILD_DIR, # we'll put the Kodi source on the same level # before_script: - - cd $TRAVIS_BUILD_DIR/.. - - git clone --branch master --depth=1 https://github.com/xbmc/xbmc.git - - cd ${app_id} && mkdir build && cd build - - mkdir -p definition/${app_id} - - echo ${app_id} $TRAVIS_BUILD_DIR $TRAVIS_COMMIT > definition/${app_id}/${app_id}.txt - - cmake -DADDONS_TO_BUILD=${app_id} -DADDON_SRC_PREFIX=$TRAVIS_BUILD_DIR/.. -DADDONS_DEFINITION_DIR=$TRAVIS_BUILD_DIR/build/definition -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$TRAVIS_BUILD_DIR/../xbmc/addons -DPACKAGE_ZIP=1 $TRAVIS_BUILD_DIR/../xbmc/cmake/addons + - if [[ $DEBIAN_BUILD != true ]]; then cd $TRAVIS_BUILD_DIR/..; fi + - if [[ $DEBIAN_BUILD != true ]]; then git clone --branch master --depth=1 https://github.com/xbmc/xbmc.git; fi + - if [[ $DEBIAN_BUILD != true ]]; then cd ${app_id} && mkdir build && cd build; fi + - if [[ $DEBIAN_BUILD != true ]]; then mkdir -p definition/${app_id}; fi + - if [[ $DEBIAN_BUILD != true ]]; then echo ${app_id} $TRAVIS_BUILD_DIR $TRAVIS_COMMIT > definition/${app_id}/${app_id}.txt; fi + - if [[ $DEBIAN_BUILD != true ]]; then cmake -DADDONS_TO_BUILD=${app_id} -DADDON_SRC_PREFIX=$TRAVIS_BUILD_DIR/.. -DADDONS_DEFINITION_DIR=$TRAVIS_BUILD_DIR/build/definition -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$TRAVIS_BUILD_DIR/../xbmc/addons -DPACKAGE_ZIP=1 $TRAVIS_BUILD_DIR/../xbmc/cmake/addons; fi + - if [[ $DEBIAN_BUILD == true ]]; then wget https://raw.githubusercontent.com/xbmc/xbmc/master/xbmc/addons/kodi-addon-dev-kit/tools/debian-addon-package-test.sh && chmod +x ./debian-addon-package-test.sh; fi + - if [[ $DEBIAN_BUILD == true ]]; then sudo apt-get build-dep $TRAVIS_BUILD_DIR; fi -script: make +script: + - if [[ $DEBIAN_BUILD != true ]]; then make; fi + - if [[ $DEBIAN_BUILD == true ]]; then ./debian-addon-package-test.sh $TRAVIS_BUILD_DIR; fi diff --git a/audiodecoder.ssf/addon.xml.in b/audiodecoder.ssf/addon.xml.in index 00782e4..b44afc5 100644 --- a/audiodecoder.ssf/addon.xml.in +++ b/audiodecoder.ssf/addon.xml.in @@ -1,7 +1,7 @@ @ADDON_DEPENDS@ @@ -12,7 +12,9 @@ tags="true" library_@PLATFORM@="@LIBRARY_FILENAME@"/> + Sega SSF/DSF Audio Decoder Sega SSF/DSF Audio Decoder + Das Sega Saturn Sound Format (SSF) und das Dreamcast Sound Format (DSF) ist ein auf PSF basierendes Audioformat. Es speichert Audio, das aus den ROMs von Sega Saturn- und Sega Dreamcast-Spielen gerippt wurde. Sega Saturn Sound Format (SSF) and Dreamcast Sound Format (DSF) is an audio format based on PSF. It stores audio ripped from the ROMs of Sega Saturn and Sega Dreamcast games. @PLATFORM@ GPL-2.0-or-later diff --git a/audiodecoder.ssf/resources/language/resource.language.de_de/strings.po b/audiodecoder.ssf/resources/language/resource.language.de_de/strings.po new file mode 100644 index 0000000..5958fe8 --- /dev/null +++ b/audiodecoder.ssf/resources/language/resource.language.de_de/strings.po @@ -0,0 +1,109 @@ +# Kodi Media Center language file +# Addon Name: SSF/DSF Audio Decoder +# Addon id: audiodecoder.ssf +# Addon Provider: Team Kodi +msgid "" +msgstr "" +"Project-Id-Version: KODI Addons\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/audiodecoder.ssf/issues/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: German (Germany) (http://www.transifex.com/projects/p/kodi-addons/language/de_DE/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de_DE\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#[Consistency] Make terms, settings names, brands and other minutiae, consistent throughout file. +#[Capitalization] Avoid capitalizing every second word. See http://grammarist.com/capitalization/ +#For example, prefer wording as "This new string" instead of "This New String". +#[Referencing] If a suitable string already exists, reuse it, making a note of where it's used! +#[Description / location] For example, "#. Description of some setting" used on "#: xbmc/addons/guidialogaddoninfo.cpp" +#When writing a description or setting, refer to a setting name in quotes. See existing entries for guidance. +#For example, "Press \"OK\" for \"All seasons\"" instead of "Press OK for All seasons" after first word. + +msgctxt "#30000" +msgid "Default length" +msgstr "Standardlänge" + +msgctxt "#30001" +msgid "Used if specified file does not provide the length." +msgstr "Wird verwendet, wenn die angegebene Datei nicht die Länge angibt." + +msgctxt "#30002" +msgid "unused" +msgstr "unbenutzt" + +msgctxt "#30003" +msgid "{0:d} s" +msgstr "{0:d} s" + +msgctxt "#30004" +msgid "Default fade out time" +msgstr "Standard-Ausblendzeit" + +msgctxt "#30005" +msgid "Used if specified file does not provide the length and fade." +msgstr "Wird verwendet, wenn angegebene Datei die Länge und verblassen nicht zur Verfügung stellt." + +msgctxt "#30006" +msgid "unused" +msgstr "unbenutzt" + +msgctxt "#30007" +msgid "{0:d} ms" +msgstr "{0:d} ms" + +msgctxt "#30008" +msgid "Suppress opening silence" +msgstr "Unterdrücke die Eröffnungsstille" + +msgctxt "#30009" +msgid "Some files start with silent data, this prevents it and looks for the beginning." +msgstr "Einige Dateien beginnen mit stillen Daten, dies verhindert dies und sucht nach dem Anfang." + +msgctxt "#30010" +msgid "Suppress end silence" +msgstr "Unterdrücke die Stille am Ende" + +msgctxt "#30011" +msgid "Some files end with silent data, this prevents it and looks for the end." +msgstr "Einige Dateien enden mit stillen Daten, dies verhindert dies und sucht nach dem Ende." + +msgctxt "#30012" +msgid "Second of silence to check" +msgstr "Sekunden der Stille zu prüfen" + +msgctxt "#30013" +msgid "How many silent seconds are allowed before playback is stopped." +msgstr "Wie viele stille Sekunden sind zulässig, bevor die Wiedergabe gestoppt wird?" + +msgctxt "#30014" +msgid "{0:d} s" +msgstr "{0:d} s" + +msgctxt "#30015" +msgid "Direct output" +msgstr "Direkte Ausgabe" + +msgctxt "#30016" +msgid "Enable direct (dry) output." +msgstr "Aktivieren Sie die direkte (trockene) Ausgabe." + +msgctxt "#30017" +msgid "DSP emulation" +msgstr "DSP-Emulation" + +msgctxt "#30018" +msgid "Enable DSP emulation (for reverb, etc.)." +msgstr "Aktivieren Sie die DSP-Emulation (für Hall usw.)." + +msgctxt "#30019" +msgid "Dynamic recompiler" +msgstr "Dynamischer Recompiler" + +msgctxt "#30020" +msgid "Emulate DSP using dynamic recompiler." +msgstr "Emulieren Sie DSP mit dem dynamischen Recompiler." diff --git a/audiodecoder.ssf/resources/language/resource.language.en_gb/strings.po b/audiodecoder.ssf/resources/language/resource.language.en_gb/strings.po index 4c0f9a9..ba3f168 100644 --- a/audiodecoder.ssf/resources/language/resource.language.en_gb/strings.po +++ b/audiodecoder.ssf/resources/language/resource.language.en_gb/strings.po @@ -1,23 +1,35 @@ +# Kodi Media Center language file +# Addon Name: SSF/DSF Audio Decoder +# Addon id: audiodecoder.ssf +# Addon Provider: Team Kodi msgid "" msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"Project-Id-Version: KODI Addons\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/audiodecoder.ssf/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: English (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/en/)\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: English (United Kingdom) (http://www.transifex.com/projects/p/kodi-addons/language/en_GB/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: en\n" +"Language: en_GB\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +#[Consistency] Make terms, settings names, brands and other minutiae, consistent throughout file. +#[Capitalization] Avoid capitalizing every second word. See http://grammarist.com/capitalization/ +#For example, prefer wording as "This new string" instead of "This New String". +#[Referencing] If a suitable string already exists, reuse it, making a note of where it's used! +#[Description / location] For example, "#. Description of some setting" used on "#: xbmc/addons/guidialogaddoninfo.cpp" +#When writing a description or setting, refer to a setting name in quotes. See existing entries for guidance. +#For example, "Press \"OK\" for \"All seasons\"" instead of "Press OK for All seasons" after first word. + msgctxt "#30000" msgid "Default length" msgstr "" msgctxt "#30001" -msgid "Used if specified file does not provide the length" +msgid "Used if specified file does not provide the length." msgstr "" msgctxt "#30002" @@ -33,7 +45,7 @@ msgid "Default fade out time" msgstr "" msgctxt "#30005" -msgid "Used if specified file does not provide the length and fade" +msgid "Used if specified file does not provide the length and fade." msgstr "" msgctxt "#30006" @@ -49,7 +61,7 @@ msgid "Suppress opening silence" msgstr "" msgctxt "#30009" -msgid "Some files start with silent data, this prevents it and looks for the beginning" +msgid "Some files start with silent data, this prevents it and looks for the beginning." msgstr "" msgctxt "#30010" @@ -57,7 +69,7 @@ msgid "Suppress end silence" msgstr "" msgctxt "#30011" -msgid "Some files end with silent data, this prevents it and looks for the end" +msgid "Some files end with silent data, this prevents it and looks for the end." msgstr "" msgctxt "#30012" @@ -65,7 +77,7 @@ msgid "Second of silence to check" msgstr "" msgctxt "#30013" -msgid "How many silent seconds are allowed before playback is stopped" +msgid "How many silent seconds are allowed before playback is stopped." msgstr "" msgctxt "#30014" @@ -77,7 +89,7 @@ msgid "Direct output" msgstr "" msgctxt "#30016" -msgid "Enable direct (dry) output" +msgid "Enable direct (dry) output." msgstr "" msgctxt "#30017" @@ -85,7 +97,7 @@ msgid "DSP emulation" msgstr "" msgctxt "#30018" -msgid "Enable DSP emulation (for reverb, etc.)" +msgid "Enable DSP emulation (for reverb, etc.)." msgstr "" msgctxt "#30019" @@ -93,5 +105,5 @@ msgid "Dynamic recompiler" msgstr "" msgctxt "#30020" -msgid "Emulate DSP using dynamic recompiler" +msgid "Emulate DSP using dynamic recompiler." msgstr "" diff --git a/debian/control b/debian/control index 15cfc30..1f1ad84 100644 --- a/debian/control +++ b/debian/control @@ -5,7 +5,7 @@ Build-Depends: debhelper (>= 9.0.0), cmake, kodi-addon-dev, zlib1g-dev Standards-Version: 4.1.2 Section: libs -Homepage: http://kodi.tv +Homepage: https://kodi.tv Package: kodi-audiodecoder-ssf Section: libs diff --git a/debian/rules b/debian/rules index 19e99da..c77678d 100755 --- a/debian/rules +++ b/debian/rules @@ -10,13 +10,10 @@ #export DH_VERBOSE=1 %: - dh $@ + dh $@ override_dh_auto_configure: - dh_auto_configure -- -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=1 -DUSE_LTO=1 - -override_dh_strip: - dh_strip --dbg-package=kodi-audiodecoder-ssf-dbg + dh_auto_configure -- -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_SHARED_LIBS=1 -DUSE_LTO=1 override_dh_installdocs: dh_installdocs --link-doc=kodi-audiodecoder-ssf diff --git a/debian/source/format b/debian/source/format index 163aaf8..89ae9db 100644 --- a/debian/source/format +++ b/debian/source/format @@ -1 +1 @@ -3.0 (quilt) +3.0 (native) diff --git a/lib/kodi-Highly_Theoretical-note.txt b/lib/kodi-Highly_Theoretical-note.txt index 4aaabd2..1c18bca 100644 --- a/lib/kodi-Highly_Theoretical-note.txt +++ b/lib/kodi-Highly_Theoretical-note.txt @@ -1,4 +1,6 @@ -Highly_Theoretical source from https://github.com/kode54/Highly_Theoretical -Sync to 2998a4b (24 Jul 2016) +Highly_Theoretical source from https://g.losno.co/chris/Highly_Theoretical +Sync to eb3f3e0682 (2 May 2019) + +Other source URL https://github.com/kode54/Highly_Theoretical Include fix build for ios/osx/android, see https://github.com/xbmc/audiodecoder.ssf/commit/41ef56f7 diff --git a/lib/kodi-psflib-note.txt b/lib/kodi-psflib-note.txt index d736f34..5b0c145 100644 --- a/lib/kodi-psflib-note.txt +++ b/lib/kodi-psflib-note.txt @@ -1,2 +1,4 @@ -psflib source from https://github.com/kode54/psflib -Sync to 6cb3515 (2 May 2019) +psflib source from https://g.losno.co/chris/psflib +Sync to 591f2a3b31 (25 May 2020) + +Old source https://github.com/kode54/psflib (38b1419 (28 Feb 2020)) diff --git a/lib/psflib/LICENSE b/lib/psflib/LICENSE new file mode 100644 index 0000000..a1d7e71 --- /dev/null +++ b/lib/psflib/LICENSE @@ -0,0 +1,21 @@ +PSFLIB - The MIT License (MIT) + +Copyright (c) 2012-2015 Christopher Snowhill + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/lib/psflib/psflib.c b/lib/psflib/psflib.c index 06a6f93..66aa279 100644 --- a/lib/psflib/psflib.c +++ b/lib/psflib/psflib.c @@ -440,7 +440,7 @@ static int psf_load_internal(psf_load_state * state, const char * file_name) strcat(full_path, file_name); #endif - file = state->file_callbacks->fopen(full_path); + file = state->file_callbacks->fopen(state->file_callbacks->context, full_path); free(full_path); diff --git a/lib/psflib/psflib.h b/lib/psflib/psflib.h index 107471c..f071f1b 100644 --- a/lib/psflib/psflib.h +++ b/lib/psflib/psflib.h @@ -1,7 +1,7 @@ /* PSFLIB - Main PSF parser implementation -Copyright (c) 2012-2015 Christopher Snowhill +Copyright (c) 2012-2020 Christopher Snowhill Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -38,9 +38,12 @@ typedef struct psf_file_callbacks /* list of characters which act as path separators, null terminated */ const char * path_separators; + /* Context pointer for fopen callback */ + void * context; + /* opens the file pointed to by path read-only in binary mode, * accepts UTF-8 encoding, returns file handle */ - void * (* fopen )(const char * path); + void * (* fopen )(void * context, const char * path); /* reads to specified buffer, returns count of size bytes read */ size_t (* fread )(void * buffer, size_t size, size_t count, void * handle); diff --git a/src/CircularBuffer.h b/src/CircularBuffer.h index a874daf..1061def 100644 --- a/src/CircularBuffer.h +++ b/src/CircularBuffer.h @@ -12,69 +12,73 @@ int const silence_threshold = 8; -template +template class circular_buffer { public: - circular_buffer( unsigned p_size ) : readptr( 0 ), writeptr( 0 ), size( p_size ), used( 0 ) + circular_buffer(unsigned p_size) : readptr(0), writeptr(0), size(p_size), used(0) { - buffer.resize( p_size ); + buffer.resize(p_size); } unsigned data_available() { return used; } unsigned free_space() { return size - used; } - bool write( const T * src, unsigned count ) + bool write(const T* src, unsigned count) { - if ( count > free_space() ) return false; - while( count ) + if (count > free_space()) + return false; + while (count) { unsigned delta = size - writeptr; - if ( delta > count ) delta = count; - std::copy( src, src + delta, buffer.begin() + writeptr ); + if (delta > count) + delta = count; + std::copy(src, src + delta, buffer.begin() + writeptr); used += delta; - writeptr = ( writeptr + delta ) % size; + writeptr = (writeptr + delta) % size; src += delta; count -= delta; } return true; } - unsigned read( T * dst, unsigned count ) + unsigned read(T* dst, unsigned count) { unsigned done = 0; - for(;;) + for (;;) { unsigned delta = size - readptr; - if ( delta > used ) delta = used; - if ( delta > count ) delta = count; - if ( !delta ) break; + if (delta > used) + delta = used; + if (delta > count) + delta = count; + if (!delta) + break; - std::copy( buffer.begin() + readptr, buffer.begin() + readptr + delta, dst ); + std::copy(buffer.begin() + readptr, buffer.begin() + readptr + delta, dst); dst += delta; done += delta; - readptr = ( readptr + delta ) % size; + readptr = (readptr + delta) % size; count -= delta; used -= delta; } return done; } - void reset() - { - readptr = writeptr = used = 0; - } + void reset() { readptr = writeptr = used = 0; } void resize(unsigned p_size) { size = p_size; - buffer.resize( p_size ); + buffer.resize(p_size); reset(); } bool test_silence() const { - T* begin = (T*) &buffer[0]; + T* begin = (T*)&buffer[0]; T first = *begin; *begin = silence_threshold * 2; T* p = begin + size; - while ( (unsigned) ( *--p + silence_threshold ) <= (unsigned) silence_threshold * 2 ) { } + while ((unsigned)(*--p + silence_threshold) <= (unsigned)silence_threshold * 2) + { + } *begin = first; - return p == begin && ( (unsigned) ( first + silence_threshold ) <= (unsigned) silence_threshold * 2 ); + return p == begin && ((unsigned)(first + silence_threshold) <= (unsigned)silence_threshold * 2); } private: diff --git a/src/SSFCodec.cpp b/src/SSFCodec.cpp index e0d1bd1..4e50953 100644 --- a/src/SSFCodec.cpp +++ b/src/SSFCodec.cpp @@ -16,226 +16,230 @@ std::mutex CSSFCodec::m_gSyncMutex; extern "C" { -inline unsigned get_le32(void const* p) -{ - return (unsigned) ((unsigned char const*) p) [3] << 24 | - (unsigned) ((unsigned char const*) p) [2] << 16 | - (unsigned) ((unsigned char const*) p) [1] << 8 | - (unsigned) ((unsigned char const*) p) [0]; -} + inline unsigned get_le32(void const* p) + { + return (unsigned)((unsigned char const*)p)[3] << 24 | + (unsigned)((unsigned char const*)p)[2] << 16 | + (unsigned)((unsigned char const*)p)[1] << 8 | (unsigned)((unsigned char const*)p)[0]; + } -static int sdsf_load(void* context, const uint8_t* exe, size_t exe_size, - const uint8_t* reserved, size_t reserved_size) -{ - if (exe_size < 4) - return -1; + static int sdsf_load(void* context, + const uint8_t* exe, + size_t exe_size, + const uint8_t* reserved, + size_t reserved_size) + { + if (exe_size < 4) + return -1; - sdsf_load_state* state = static_cast(context); + sdsf_load_state* state = static_cast(context); - std::vector& dst = state->state; + std::vector& dst = state->state; + + if (dst.size() < 4) + { + dst.resize(exe_size); + memcpy(&dst[0], exe, exe_size); + return 0; + } + + uint32_t dst_start = get_le32(&dst[0]); + uint32_t src_start = get_le32(exe); + dst_start &= 0x7FFFFF; + src_start &= 0x7FFFFF; + size_t dst_len = dst.size() - 4; + size_t src_len = exe_size - 4; + if (dst_len > 0x800000) + dst_len = 0x800000; + if (src_len > 0x800000) + src_len = 0x800000; + + if (src_start < dst_start) + { + size_t diff = dst_start - src_start; + dst.resize(dst_len + 4 + diff); + memmove(&dst[0] + 4 + diff, &dst[0] + 4, dst_len); + memset(&dst[0] + 4, 0, diff); + dst_len += diff; + dst_start = src_start; + *(uint32_t*)(&dst[0]) = get_le32(&dst_start); + } + if ((src_start + src_len) > (dst_start + dst_len)) + { + size_t diff = (src_start + src_len) - (dst_start + dst_len); + dst.resize(dst_len + 4 + diff); + memset(&dst[0] + 4 + dst_len, 0, diff); + dst_len += diff; + } + + memcpy(&dst[0] + 4 + (src_start - dst_start), exe + 4, src_len); - if (dst.size() < 4) - { - dst.resize(exe_size); - memcpy(&dst[0], exe, exe_size); return 0; } - uint32_t dst_start = get_le32(&dst[0]); - uint32_t src_start = get_le32(exe); - dst_start &= 0x7FFFFF; - src_start &= 0x7FFFFF; - size_t dst_len = dst.size() - 4; - size_t src_len = exe_size - 4; - if (dst_len > 0x800000) - dst_len = 0x800000; - if (src_len > 0x800000) - src_len = 0x800000; - - if (src_start < dst_start) + static void* psf_file_fopen(void* context, const char* uri) { - size_t diff = dst_start - src_start; - dst.resize(dst_len + 4 + diff); - memmove(&dst[0] + 4 + diff, &dst[0] + 4, dst_len); - memset(&dst[0] + 4, 0, diff ); - dst_len += diff; - dst_start = src_start; - *(uint32_t*)(&dst[0]) = get_le32(&dst_start); + kodi::vfs::CFile* file = new kodi::vfs::CFile; + if (!file->OpenFile(uri, 0)) + { + delete file; + return nullptr; + } + + return file; } - if ((src_start + src_len) > (dst_start + dst_len)) + + static size_t psf_file_fread(void* buffer, size_t size, size_t count, void* handle) { - size_t diff = (src_start + src_len) - (dst_start + dst_len); - dst.resize(dst_len + 4 + diff); - memset(&dst[0] + 4 + dst_len, 0, diff); - dst_len += diff; + kodi::vfs::CFile* file = static_cast(handle); + return file->Read(buffer, size * count); } - memcpy(&dst[0] + 4 + (src_start - dst_start), exe + 4, src_len); - - return 0; -} - -static void* psf_file_fopen(const char* uri) -{ - kodi::vfs::CFile* file = new kodi::vfs::CFile; - if (!file->OpenFile(uri, 0)) + static int psf_file_fseek(void* handle, int64_t offset, int whence) { - delete file; - return nullptr; + kodi::vfs::CFile* file = static_cast(handle); + return file->Seek(offset, whence) > -1 ? 0 : -1; } - return file; -} - -static size_t psf_file_fread(void* buffer, size_t size, size_t count, void* handle) -{ - kodi::vfs::CFile* file = static_cast(handle); - return file->Read(buffer, size*count); -} - -static int psf_file_fseek(void* handle, int64_t offset, int whence) -{ - kodi::vfs::CFile* file = static_cast(handle); - return file->Seek(offset, whence) > -1 ? 0 : -1; -} - -static int psf_file_fclose(void* handle ) -{ - delete static_cast(handle); + static int psf_file_fclose(void* handle) + { + delete static_cast(handle); - return 0; -} + return 0; + } -static long psf_file_ftell(void* handle) -{ - kodi::vfs::CFile* file = static_cast(handle); - return file->GetPosition(); -} + static long psf_file_ftell(void* handle) + { + kodi::vfs::CFile* file = static_cast(handle); + return file->GetPosition(); + } -const psf_file_callbacks psf_file_system = -{ - "\\/", - psf_file_fopen, - psf_file_fread, - psf_file_fseek, - psf_file_fclose, - psf_file_ftell -}; + const psf_file_callbacks psf_file_system = {"\\/", nullptr, psf_file_fopen, + psf_file_fread, psf_file_fseek, psf_file_fclose, + psf_file_ftell}; #define BORK_TIME 0xC0CAC01A -static unsigned long parse_time_crap(const char* input) -{ - unsigned long value = 0; - unsigned long multiplier = 1000; - const char* ptr = input; - unsigned long colon_count = 0; - - while (*ptr && ((*ptr >= '0' && *ptr <= '9') || *ptr == ':')) - { - colon_count += *ptr == ':'; - ++ptr; - } - if (colon_count > 2) - return BORK_TIME; - if (*ptr && *ptr != '.' && *ptr != ',') - return BORK_TIME; - if (*ptr) - ++ptr; - while (*ptr && *ptr >= '0' && *ptr <= '9') - ++ptr; - if (*ptr) - return BORK_TIME; - - ptr = strrchr(input, ':'); - if (!ptr) - ptr = input; - for (;;) + static unsigned long parse_time_crap(const char* input) { - char* end; - if (ptr != input) - ++ptr; - if (multiplier == 1000) + unsigned long value = 0; + unsigned long multiplier = 1000; + const char* ptr = input; + unsigned long colon_count = 0; + + while (*ptr && ((*ptr >= '0' && *ptr <= '9') || *ptr == ':')) { - double temp = std::stod(ptr); - if (temp >= 60.0) - return BORK_TIME; - value = (long)(temp * 1000.0f); + colon_count += *ptr == ':'; + ++ptr; } - else + if (colon_count > 2) + return BORK_TIME; + if (*ptr && *ptr != '.' && *ptr != ',') + return BORK_TIME; + if (*ptr) + ++ptr; + while (*ptr && *ptr >= '0' && *ptr <= '9') + ++ptr; + if (*ptr) + return BORK_TIME; + + ptr = strrchr(input, ':'); + if (!ptr) + ptr = input; + for (;;) { - unsigned long temp = strtoul(ptr, &end, 10); - if (temp >= 60 && multiplier < 3600000) - return BORK_TIME; - value += temp * multiplier; + char* end; + if (ptr != input) + ++ptr; + if (multiplier == 1000) + { + double temp = std::stod(ptr); + if (temp >= 60.0) + return BORK_TIME; + value = (long)(temp * 1000.0f); + } + else + { + unsigned long temp = strtoul(ptr, &end, 10); + if (temp >= 60 && multiplier < 3600000) + return BORK_TIME; + value += temp * multiplier; + } + if (ptr == input) + break; + ptr -= 2; + while (ptr > input && *ptr != ':') + --ptr; + multiplier *= 60; } - if (ptr == input) - break; - ptr -= 2; - while (ptr > input && *ptr != ':') - --ptr; - multiplier *= 60; - } - - return value; -} - -static int psf_info_meta(void* context, const char* name, const char* value) -{ - psf_info_meta_state* state = static_cast(context); - if (!strcasecmp(name, "artist") && state->artist.empty()) - { - state->artist = value; - } - else if (!strcasecmp(name, "game")) - { - state->artist = value; - } - else if (!strcasecmp(name, "title")) - { - state->title = value; - } - else if (!strcasecmp(name, "year")) - { - state->year = value; + return value; } - else if (!strcasecmp(name, "replaygain_")) - { - state->replaygain = value; - } - else if (!strcasecmp(name, "length")) + + static int psf_info_meta(void* context, const char* name, const char* value) { - int temp = parse_time_crap(value); - if (temp != BORK_TIME) + psf_info_meta_state* state = static_cast(context); + + if (!strcasecmp(name, "artist") && state->artist.empty()) { - state->tagSongMs = temp; + state->artist = value; } - } - else if (!strcasecmp(name, "fade")) - { - int temp = parse_time_crap(value); - if (temp != BORK_TIME) + else if (!strcasecmp(name, "game")) { - state->tagFadeMs = temp; + state->game = value; + } + else if (!strcasecmp(name, "title")) + { + state->title = value; + } + else if (!strcasecmp(name, "year")) + { + state->year = value; + } + else if (!strcasecmp(name, "genre")) + { + state->genre = value; + } + else if (!strcasecmp(name, "comment")) + { + state->comment = value; + } + else if (!strcasecmp(name, "replaygain_")) + { + state->replaygain = value; + } + else if (!strcasecmp(name, "length")) + { + int temp = parse_time_crap(value); + if (temp != BORK_TIME) + { + state->tagSongMs = temp; + } + } + else if (!strcasecmp(name, "fade")) + { + int temp = parse_time_crap(value); + if (temp != BORK_TIME) + { + state->tagFadeMs = temp; + } + } + else if (!strcasecmp(name, "utf8")) + { + state->utf8 = true; + } + else if (!strcasecmp(name, "_lib")) + { + // Unused, checked to prevent on next error + } + else if (name[0] == '_') + { + kodi::Log(ADDON_LOG_WARNING, "Unsupported tag found: '%s', required to play file", name); + return -1; } - } - else if (!strcasecmp(name, "utf8")) - { - state->utf8 = true; - } - else if (!strcasecmp(name, "_lib")) - { - // Unused, checked to prevent on next error - } - else if (name[0] == '_') - { - kodi::Log(ADDON_LOG_WARNING, "Unsupported tag found: '%s', required to play file", name); - return -1; - } - return 0; -} + return 0; + } } // extern "C" @@ -244,7 +248,6 @@ static int psf_info_meta(void* context, const char* name, const char* value) CSSFCodec::CSSFCodec(KODI_HANDLE instance, const std::string& version) : CInstanceAudioDecoder(instance, version) { - } CSSFCodec::~CSSFCodec() @@ -267,17 +270,19 @@ CSSFCodec::~CSSFCodec() yam_unprepare_dynacode(yam); } -bool CSSFCodec::Init(const std::string& filename, unsigned int filecache, - int& channels, int& samplerate, - int& bitspersample, int64_t& totaltime, - int& bitrate, AEDataFormat& format, - std::vector& channellist) +bool CSSFCodec::Init(const std::string& filename, + unsigned int filecache, + int& channels, + int& samplerate, + int& bitspersample, + int64_t& totaltime, + int& bitrate, + AudioEngineDataFormat& format, + std::vector& channellist) { m_path = filename; - m_xsfVersion = psf_load(m_path.c_str(), &psf_file_system, 0, - nullptr, nullptr, - nullptr, nullptr, 0, - SSFPrintMessage, this); + m_xsfVersion = psf_load(m_path.c_str(), &psf_file_system, 0, nullptr, nullptr, nullptr, nullptr, + 0, SSFPrintMessage, this); if (m_xsfVersion <= 0 || (m_xsfVersion != 0x11 && m_xsfVersion != 0x12)) { kodi::Log(ADDON_LOG_ERROR, "%s: Not a SSF or PSF file '%s'", __func__, m_path.c_str()); @@ -285,10 +290,8 @@ bool CSSFCodec::Init(const std::string& filename, unsigned int filecache, } psf_info_meta_state info_state; - int ret = psf_load(m_path.c_str(), &psf_file_system, m_xsfVersion, - nullptr, nullptr, - psf_info_meta, &info_state, 0, - SSFPrintMessage, this); + int ret = psf_load(m_path.c_str(), &psf_file_system, m_xsfVersion, nullptr, nullptr, + psf_info_meta, &info_state, 0, SSFPrintMessage, this); if (ret <= 0) { kodi::Log(ADDON_LOG_ERROR, "%s: Failed to load tags from '%s'", __func__, m_path.c_str()); @@ -315,8 +318,8 @@ bool CSSFCodec::Init(const std::string& filename, unsigned int filecache, return false; totaltime = m_songLength / m_cfgDefaultSampleRate * 1000 + m_tagFadeMs; - format = AE_FMT_S16NE; - channellist = { AE_CH_FL, AE_CH_FR }; + format = AUDIOENGINE_FMT_S16NE; + channellist = {AUDIOENGINE_CH_FL, AUDIOENGINE_CH_FR}; channels = 2; bitspersample = 16; bitrate = 0.0; @@ -377,7 +380,7 @@ bool CSSFCodec::Load() } else { - void * satsound = sega_get_satsound_state(pEmu); + void* satsound = sega_get_satsound_state(pEmu); yam = satsound_get_yam_state(satsound); } if (yam) @@ -385,10 +388,8 @@ bool CSSFCodec::Load() } sdsf_load_state state; - int ret = psf_load(m_path.c_str(), &psf_file_system, m_xsfVersion, - sdsf_load, &state, - nullptr, nullptr, 0, - SSFPrintMessage, this); + int ret = psf_load(m_path.c_str(), &psf_file_system, m_xsfVersion, sdsf_load, &state, nullptr, + nullptr, 0, SSFPrintMessage, this); if (ret < 0) { kodi::Log(ADDON_LOG_ERROR, "%s: Invalid SSF/DSF from '%s'", __func__, m_path.c_str()); @@ -398,7 +399,7 @@ bool CSSFCodec::Load() uint32_t start = get_le32(state.state.data()); size_t length = state.state.size(); size_t max_length = (m_xsfVersion == 0x12) ? 0x800000 : 0x80000; - if ((start + (length-4)) > max_length) + if ((start + (length - 4)) > max_length) { length = max_length - start + 4; } @@ -428,7 +429,7 @@ bool CSSFCodec::Load() if (skip_howmany > 8192) skip_howmany = 8192; m_sampleBuffer.resize(skip_howmany * 2); - int rtn = sega_execute(pEmu, 0x7FFFFFFF, m_sampleBuffer.data(), & skip_howmany); + int rtn = sega_execute(pEmu, 0x7FFFFFFF, m_sampleBuffer.data(), &skip_howmany); if (rtn < 0) { kodi::Log(ADDON_LOG_ERROR, "%s: Failed to call 'sega_execute'", __func__); @@ -471,7 +472,9 @@ int CSSFCodec::ReadPCM(uint8_t* buffer, int size, int& actualsize) if (m_eof && !m_silenceTestBuffer.data_available()) return 1; - if (m_noLoop && m_tagSongMs && (m_posDelta + mul_div(m_dataWritten, 1000, m_cfgDefaultSampleRate)) >= m_tagSongMs + m_tagFadeMs ) + if (m_noLoop && m_tagSongMs && + (m_posDelta + mul_div(m_dataWritten, 1000, m_cfgDefaultSampleRate)) >= + m_tagSongMs + m_tagFadeMs) return -1; unsigned int written = 0; @@ -511,7 +514,8 @@ int CSSFCodec::ReadPCM(uint8_t* buffer, int size, int& actualsize) samples_to_render = free_space; if (samples_to_render > usedSize) samples_to_render = usedSize; - int err = sega_execute(m_segaState.data(), 0x7FFFFFFF, m_sampleBuffer.data(), &samples_to_render); + int err = sega_execute(m_segaState.data(), 0x7FFFFFFF, m_sampleBuffer.data(), + &samples_to_render); if (err < 0 || !samples_to_render) { kodi::Log(ADDON_LOG_ERROR, "%s: Execution halted with an error", __func__); @@ -546,7 +550,7 @@ int CSSFCodec::ReadPCM(uint8_t* buffer, int size, int& actualsize) else { written = samples; - int err = sega_execute(m_segaState.data(), 0x7FFFFFFF, m_sampleBuffer.data(), & written ); + int err = sega_execute(m_segaState.data(), 0x7FFFFFFF, m_sampleBuffer.data(), &written); if (err < 0 || !written) { kodi::Log(ADDON_LOG_ERROR, "%s: Execution halted with an error", __func__); @@ -601,7 +605,8 @@ int64_t CSSFCodec::Seek(int64_t time) double p_seconds = double(time) / 1000.0; m_eof = false; - double buffered_time = (double)(m_silenceTestBuffer.data_available() / 2) / double(m_cfgDefaultSampleRate); + double buffered_time = + (double)(m_silenceTestBuffer.data_available() / 2) / double(m_cfgDefaultSampleRate); m_xsfEmuPosition += buffered_time; @@ -611,7 +616,8 @@ int64_t CSSFCodec::Seek(int64_t time) { Load(); } - unsigned int howmany = (int)(time_to_samples(p_seconds - m_xsfEmuPosition, m_cfgDefaultSampleRate)); + unsigned int howmany = + (int)(time_to_samples(p_seconds - m_xsfEmuPosition, m_cfgDefaultSampleRate)); // more abortable, and emu doesn't like doing huge numbers of samples per call anyway void* pEmu = m_segaState.data(); @@ -621,7 +627,7 @@ int64_t CSSFCodec::Seek(int64_t time) if (todo > 2048) todo = 2048; int rtn = sega_execute(pEmu, 0x7FFFFFFF, 0, &todo); - if (rtn < 0 || ! todo) + if (rtn < 0 || !todo) { m_eof = true; return -1; @@ -638,13 +644,10 @@ int64_t CSSFCodec::Seek(int64_t time) return time; } -bool CSSFCodec::ReadTag(const std::string& file, std::string& title, - std::string& artist, int& length) +bool CSSFCodec::ReadTag(const std::string& filename, kodi::addon::AudioDecoderInfoTag& tag) { - int xsfVersion = psf_load(file.c_str(), &psf_file_system, 0, - nullptr, nullptr, - nullptr, nullptr, 0, - SSFPrintMessage, this); + int xsfVersion = psf_load(filename.c_str(), &psf_file_system, 0, nullptr, nullptr, nullptr, + nullptr, 0, SSFPrintMessage, this); if (xsfVersion <= 0 || (xsfVersion != 0x11 && xsfVersion != 0x12)) { kodi::Log(ADDON_LOG_ERROR, "%s: Not a SSF or PSF file '%s'", __func__, m_path.c_str()); @@ -652,15 +655,24 @@ bool CSSFCodec::ReadTag(const std::string& file, std::string& title, } psf_info_meta_state info_state; - if (psf_load(file.c_str(), &psf_file_system, xsfVersion, nullptr, nullptr, psf_info_meta, &info_state, 0, SSFPrintMessage, this) <= 0) + if (psf_load(filename.c_str(), &psf_file_system, xsfVersion, nullptr, nullptr, psf_info_meta, + &info_state, 0, SSFPrintMessage, this) <= 0) { - kodi::Log(ADDON_LOG_ERROR, "%s: Failed to load %s information from '%s'", __func__, xsfVersion == 0x11 ? "SSF" : "DSF", file.c_str()); + kodi::Log(ADDON_LOG_ERROR, "%s: Failed to load %s information from '%s'", __func__, + xsfVersion == 0x11 ? "SSF" : "DSF", filename.c_str()); return false; } - title = info_state.title; - artist = info_state.artist; - length = (info_state.tagSongMs+info_state.tagFadeMs)/1000; + tag.SetTitle(info_state.title); + if (!info_state.artist.empty()) + tag.SetArtist(info_state.artist); + else + tag.SetArtist(info_state.game); + tag.SetAlbum(info_state.game); + tag.SetGenre(info_state.genre); + tag.SetReleaseDate(info_state.year); + tag.SetComment(info_state.comment); + tag.SetDuration((info_state.tagSongMs + info_state.tagFadeMs) / 1000); return true; } @@ -676,7 +688,11 @@ class ATTRIBUTE_HIDDEN CMyAddon : public kodi::addon::CAddonBase { public: CMyAddon() = default; - ADDON_STATUS CreateInstance(int instanceType, const std::string& instanceID, KODI_HANDLE instance, const std::string& version, KODI_HANDLE& addonInstance) override + ADDON_STATUS CreateInstance(int instanceType, + const std::string& instanceID, + KODI_HANDLE instance, + const std::string& version, + KODI_HANDLE& addonInstance) override { addonInstance = new CSSFCodec(instance, version); return ADDON_STATUS_OK; diff --git a/src/SSFCodec.h b/src/SSFCodec.h index 518e162..5bf4b03 100644 --- a/src/SSFCodec.h +++ b/src/SSFCodec.h @@ -9,20 +9,18 @@ #pragma once #include "CircularBuffer.h" - -#include -#include +#include "dcsound.h" +#include "psflib.h" +#include "satsound.h" +#include "sega.h" +#include "yam.h" #include -#include +#include +#include #include #include - -#include "sega.h" -#include "dcsound.h" -#include "satsound.h" -#include "yam.h" -#include "psflib.h" +#include struct sdsf_load_state { @@ -33,8 +31,11 @@ struct psf_info_meta_state { std::string title; std::string artist; + std::string game; + std::string genre; std::string year; std::string replaygain; + std::string comment; bool utf8 = false; @@ -48,15 +49,18 @@ class ATTRIBUTE_HIDDEN CSSFCodec : public kodi::addon::CInstanceAudioDecoder CSSFCodec(KODI_HANDLE instance, const std::string& version); ~CSSFCodec() override; - bool Init(const std::string& filename, unsigned int filecache, - int& channels, int& samplerate, - int& bitspersample, int64_t& totaltime, - int& bitrate, AEDataFormat& format, - std::vector& channellist) override; + bool Init(const std::string& filename, + unsigned int filecache, + int& channels, + int& samplerate, + int& bitspersample, + int64_t& totaltime, + int& bitrate, + AudioEngineDataFormat& format, + std::vector& channellist) override; int ReadPCM(uint8_t* buffer, int size, int& actualsize) override; int64_t Seek(int64_t time) override; - bool ReadTag(const std::string& file, std::string& title, - std::string& artist, int& length) override; + bool ReadTag(const std::string& filename, kodi::addon::AudioDecoderInfoTag& tag) override; private: static void SSFPrintMessage(void* context, const char* message); @@ -73,8 +77,8 @@ class ATTRIBUTE_HIDDEN CSSFCodec : public kodi::addon::CInstanceAudioDecoder inline void calcfade() { - m_songLength = mul_div(m_tagSongMs-m_posDelta,44100,1000); - m_fadeLength = mul_div(m_tagFadeMs,44100,1000); + m_songLength = mul_div(m_tagSongMs - m_posDelta, 44100, 1000); + m_fadeLength = mul_div(m_tagFadeMs, 44100, 1000); } inline int mul_div(int number, int numerator, int denominator) @@ -82,7 +86,7 @@ class ATTRIBUTE_HIDDEN CSSFCodec : public kodi::addon::CInstanceAudioDecoder long long ret = number; ret *= numerator; ret /= denominator; - return (int) ret; + return (int)ret; } int m_cfgDefaultSampleRate = 44100; @@ -118,4 +122,3 @@ class ATTRIBUTE_HIDDEN CSSFCodec : public kodi::addon::CInstanceAudioDecoder int m_tagSongMs; int m_tagFadeMs; }; -