diff --git a/ESMusicExtractor.xcodeproj/project.pbxproj b/ESMusicExtractor.xcodeproj/project.pbxproj index 63762fb..7bcc5d3 100644 --- a/ESMusicExtractor.xcodeproj/project.pbxproj +++ b/ESMusicExtractor.xcodeproj/project.pbxproj @@ -493,10 +493,10 @@ C0245CD4212DBC6C00DBFEA3 /* extractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C01377DB211A06090046020A /* extractor.cpp */; }; C0245CD5212DBC7200DBFEA3 /* keyextractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C01377DF211A06090046020A /* keyextractor.cpp */; }; C0245CD6212DBC7500DBFEA3 /* levelextractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C01377E1211A06090046020A /* levelextractor.cpp */; }; + C037276621304F4D00E9C15C /* audioloader_ios.h in Headers */ = {isa = PBXBuildFile; fileRef = C037276421304F4C00E9C15C /* audioloader_ios.h */; }; C088C619211B54C3009ED9DB /* taglib_config.h in Headers */ = {isa = PBXBuildFile; fileRef = C088C618211B54C3009ED9DB /* taglib_config.h */; }; C088CB10211B561C009ED9DB /* checked.h in Headers */ = {isa = PBXBuildFile; fileRef = C088C961211B561C009ED9DB /* checked.h */; }; C088CB11211B561C009ED9DB /* core.h in Headers */ = {isa = PBXBuildFile; fileRef = C088C962211B561C009ED9DB /* core.h */; }; - C088CB30211B561C009ED9DB /* ape-tag-format.txt in Resources */ = {isa = PBXBuildFile; fileRef = C088C989211B561C009ED9DB /* ape-tag-format.txt */; }; C088CB31211B561C009ED9DB /* apefile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C088C98A211B561C009ED9DB /* apefile.cpp */; }; C088CB32211B561C009ED9DB /* apefile.h in Headers */ = {isa = PBXBuildFile; fileRef = C088C98B211B561C009ED9DB /* apefile.h */; }; C088CB33211B561C009ED9DB /* apefooter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C088C98C211B561C009ED9DB /* apefooter.cpp */; }; @@ -599,10 +599,6 @@ C088CB95211B561D009ED9DB /* unsynchronizedlyricsframe.h in Headers */ = {isa = PBXBuildFile; fileRef = C088C9F8211B561C009ED9DB /* unsynchronizedlyricsframe.h */; }; C088CB96211B561D009ED9DB /* urllinkframe.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C088C9F9211B561C009ED9DB /* urllinkframe.cpp */; }; C088CB97211B561D009ED9DB /* urllinkframe.h in Headers */ = {isa = PBXBuildFile; fileRef = C088C9FA211B561C009ED9DB /* urllinkframe.h */; }; - C088CB98211B561D009ED9DB /* id3v2.2.0.txt in Resources */ = {isa = PBXBuildFile; fileRef = C088C9FB211B561C009ED9DB /* id3v2.2.0.txt */; }; - C088CB99211B561D009ED9DB /* id3v2.3.0.txt in Resources */ = {isa = PBXBuildFile; fileRef = C088C9FC211B561C009ED9DB /* id3v2.3.0.txt */; }; - C088CB9A211B561D009ED9DB /* id3v2.4.0-frames.txt in Resources */ = {isa = PBXBuildFile; fileRef = C088C9FD211B561C009ED9DB /* id3v2.4.0-frames.txt */; }; - C088CB9B211B561D009ED9DB /* id3v2.4.0-structure.txt in Resources */ = {isa = PBXBuildFile; fileRef = C088C9FE211B561C009ED9DB /* id3v2.4.0-structure.txt */; }; C088CB9C211B561D009ED9DB /* id3v2extendedheader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C088C9FF211B561C009ED9DB /* id3v2extendedheader.cpp */; }; C088CB9D211B561D009ED9DB /* id3v2extendedheader.h in Headers */ = {isa = PBXBuildFile; fileRef = C088CA00211B561C009ED9DB /* id3v2extendedheader.h */; }; C088CB9E211B561D009ED9DB /* id3v2footer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C088CA01211B561C009ED9DB /* id3v2footer.cpp */; }; @@ -716,25 +712,15 @@ C088CC0D211B561D009ED9DB /* xmproperties.h in Headers */ = {isa = PBXBuildFile; fileRef = C088CA7D211B561C009ED9DB /* xmproperties.h */; }; C088CC9C211B57F1009ED9DB /* metadatareader.h in Headers */ = {isa = PBXBuildFile; fileRef = C088CC9A211B57F0009ED9DB /* metadatareader.h */; }; C088CC9D211B57F1009ED9DB /* metadatareader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C088CC9B211B57F1009ED9DB /* metadatareader.cpp */; }; - C0B559EB211B2079007817F6 /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = C0B559EA211B2079007817F6 /* libiconv.tbd */; }; - C0B559ED211B20A2007817F6 /* libbz2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = C0B559EC211B20A2007817F6 /* libbz2.tbd */; }; - C0B559EF211B20A9007817F6 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = C0B559EE211B20A9007817F6 /* libz.tbd */; }; C0B559F1211B20C5007817F6 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0B559F0211B20C4007817F6 /* AudioToolbox.framework */; }; C0B559F3211B20CB007817F6 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0B559F2211B20CB007817F6 /* Accelerate.framework */; }; C0B559F4211B23C4007817F6 /* libsamplerate.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C0F3BE8D211B0EED00073488 /* libsamplerate.a */; }; - C0B55A07211B27D0007817F6 /* audioloader_ios.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C0B559FE211B27D0007817F6 /* audioloader_ios.cpp */; }; - C0B55A08211B27D0007817F6 /* audioloader_ios.h in Headers */ = {isa = PBXBuildFile; fileRef = C0B559FF211B27D0007817F6 /* audioloader_ios.h */; }; C0B55A09211B27D0007817F6 /* essentia_algorithms_reg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C0B55A00211B27D0007817F6 /* essentia_algorithms_reg.cpp */; }; - C0B55A0A211B27D0007817F6 /* ffmpegapi.h in Headers */ = {isa = PBXBuildFile; fileRef = C0B55A01211B27D0007817F6 /* ffmpegapi.h */; }; C0B55A0B211B27D0007817F6 /* extractor_utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C0B55A03211B27D0007817F6 /* extractor_utils.cpp */; }; C0B55A0C211B27D0007817F6 /* extractor_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = C0B55A04211B27D0007817F6 /* extractor_utils.h */; }; C0B55A0D211B27D0007817F6 /* streaming_extractor_music.h in Headers */ = {isa = PBXBuildFile; fileRef = C0B55A05211B27D0007817F6 /* streaming_extractor_music.h */; }; C0B55A0E211B27D0007817F6 /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = C0B55A06211B27D0007817F6 /* version.h */; }; - C0BA3B8E211A31E90038D19F /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = C0BA3B8D211A31E90038D19F /* libc++.tbd */; }; - C0E7A20C211A2F6700711656 /* libavcodec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C0E7A1A3211A2F6600711656 /* libavcodec.a */; }; - C0E7A20F211A2F6700711656 /* libavformat.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C0E7A1A6211A2F6600711656 /* libavformat.a */; }; - C0E7A210211A2F6700711656 /* libavutil.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C0E7A1A7211A2F6600711656 /* libavutil.a */; }; - C0E7A211211A2F6700711656 /* libswresample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C0E7A1A8211A2F6600711656 /* libswresample.a */; }; + C0B9C2662130872E0029DA6F /* audioloader_ios.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C037276321304F4C00E9C15C /* audioloader_ios.cpp */; }; C0E7A21D211A30FE00711656 /* ESExtractor.h in Headers */ = {isa = PBXBuildFile; fileRef = C0E7A21A211A30FE00711656 /* ESExtractor.h */; settings = {ATTRIBUTES = (Public, ); }; }; C0E7A21E211A30FE00711656 /* ESExtractor.mm in Sources */ = {isa = PBXBuildFile; fileRef = C0E7A21B211A30FE00711656 /* ESExtractor.mm */; }; /* End PBXBuildFile section */ @@ -1344,10 +1330,11 @@ C0137A36211A06090046020A /* tnt_version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tnt_version.h; sourceTree = ""; }; C0138400211A06BD0046020A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; C0138401211A06BD0046020A /* ESMusicExtractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ESMusicExtractor.h; sourceTree = ""; }; + C037276321304F4C00E9C15C /* audioloader_ios.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = audioloader_ios.cpp; sourceTree = ""; }; + C037276421304F4C00E9C15C /* audioloader_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audioloader_ios.h; sourceTree = ""; }; C088C618211B54C3009ED9DB /* taglib_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = taglib_config.h; sourceTree = ""; }; C088C961211B561C009ED9DB /* checked.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = checked.h; sourceTree = ""; }; C088C962211B561C009ED9DB /* core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = core.h; sourceTree = ""; }; - C088C989211B561C009ED9DB /* ape-tag-format.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "ape-tag-format.txt"; sourceTree = ""; }; C088C98A211B561C009ED9DB /* apefile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = apefile.cpp; sourceTree = ""; }; C088C98B211B561C009ED9DB /* apefile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = apefile.h; sourceTree = ""; }; C088C98C211B561C009ED9DB /* apefooter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = apefooter.cpp; sourceTree = ""; }; @@ -1450,10 +1437,6 @@ C088C9F8211B561C009ED9DB /* unsynchronizedlyricsframe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unsynchronizedlyricsframe.h; sourceTree = ""; }; C088C9F9211B561C009ED9DB /* urllinkframe.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = urllinkframe.cpp; sourceTree = ""; }; C088C9FA211B561C009ED9DB /* urllinkframe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = urllinkframe.h; sourceTree = ""; }; - C088C9FB211B561C009ED9DB /* id3v2.2.0.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = id3v2.2.0.txt; sourceTree = ""; }; - C088C9FC211B561C009ED9DB /* id3v2.3.0.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = id3v2.3.0.txt; sourceTree = ""; }; - C088C9FD211B561C009ED9DB /* id3v2.4.0-frames.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "id3v2.4.0-frames.txt"; sourceTree = ""; }; - C088C9FE211B561C009ED9DB /* id3v2.4.0-structure.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "id3v2.4.0-structure.txt"; sourceTree = ""; }; C088C9FF211B561C009ED9DB /* id3v2extendedheader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = id3v2extendedheader.cpp; sourceTree = ""; }; C088CA00211B561C009ED9DB /* id3v2extendedheader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = id3v2extendedheader.h; sourceTree = ""; }; C088CA01211B561C009ED9DB /* id3v2footer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = id3v2footer.cpp; sourceTree = ""; }; @@ -1567,27 +1550,16 @@ C088CA7D211B561C009ED9DB /* xmproperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xmproperties.h; sourceTree = ""; }; C088CC9A211B57F0009ED9DB /* metadatareader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = metadatareader.h; sourceTree = ""; }; C088CC9B211B57F1009ED9DB /* metadatareader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = metadatareader.cpp; sourceTree = ""; }; - C0B559EA211B2079007817F6 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; }; - C0B559EC211B20A2007817F6 /* libbz2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbz2.tbd; path = usr/lib/libbz2.tbd; sourceTree = SDKROOT; }; - C0B559EE211B20A9007817F6 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; C0B559F0211B20C4007817F6 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; C0B559F2211B20CB007817F6 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; C0B559F9211B2451007817F6 /* polartocartesian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = polartocartesian.h; sourceTree = ""; }; C0B559FA211B2451007817F6 /* polartocartesian.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = polartocartesian.cpp; sourceTree = ""; }; - C0B559FE211B27D0007817F6 /* audioloader_ios.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = audioloader_ios.cpp; sourceTree = ""; }; - C0B559FF211B27D0007817F6 /* audioloader_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audioloader_ios.h; sourceTree = ""; }; C0B55A00211B27D0007817F6 /* essentia_algorithms_reg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = essentia_algorithms_reg.cpp; sourceTree = ""; }; - C0B55A01211B27D0007817F6 /* ffmpegapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffmpegapi.h; sourceTree = ""; }; C0B55A03211B27D0007817F6 /* extractor_utils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = extractor_utils.cpp; sourceTree = ""; }; C0B55A04211B27D0007817F6 /* extractor_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = extractor_utils.h; sourceTree = ""; }; C0B55A05211B27D0007817F6 /* streaming_extractor_music.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = streaming_extractor_music.h; sourceTree = ""; }; C0B55A06211B27D0007817F6 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; C0B55A0F211B2E0F007817F6 /* ESMusicExtractor.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ESMusicExtractor.xcconfig; sourceTree = ""; }; - C0BA3B8D211A31E90038D19F /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; - C0E7A1A3211A2F6600711656 /* libavcodec.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libavcodec.a; sourceTree = ""; }; - C0E7A1A6211A2F6600711656 /* libavformat.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libavformat.a; sourceTree = ""; }; - C0E7A1A7211A2F6600711656 /* libavutil.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libavutil.a; sourceTree = ""; }; - C0E7A1A8211A2F6600711656 /* libswresample.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libswresample.a; sourceTree = ""; }; C0E7A21A211A30FE00711656 /* ESExtractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ESExtractor.h; sourceTree = ""; }; C0E7A21B211A30FE00711656 /* ESExtractor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ESExtractor.mm; sourceTree = ""; }; C0F3BE87211B0EED00073488 /* samplerate.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = samplerate.xcodeproj; path = samplerate/samplerate.xcodeproj; sourceTree = ""; }; @@ -1601,14 +1573,6 @@ C0B559F4211B23C4007817F6 /* libsamplerate.a in Frameworks */, C0B559F3211B20CB007817F6 /* Accelerate.framework in Frameworks */, C0B559F1211B20C5007817F6 /* AudioToolbox.framework in Frameworks */, - C0B559EF211B20A9007817F6 /* libz.tbd in Frameworks */, - C0B559ED211B20A2007817F6 /* libbz2.tbd in Frameworks */, - C0B559EB211B2079007817F6 /* libiconv.tbd in Frameworks */, - C0BA3B8E211A31E90038D19F /* libc++.tbd in Frameworks */, - C0E7A210211A2F6700711656 /* libavutil.a in Frameworks */, - C0E7A20C211A2F6700711656 /* libavcodec.a in Frameworks */, - C0E7A211211A2F6700711656 /* libswresample.a in Frameworks */, - C0E7A20F211A2F6700711656 /* libavformat.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1641,7 +1605,6 @@ children = ( C088C95A211B561C009ED9DB /* taglib */, C0F3BE87211B0EED00073488 /* samplerate.xcodeproj */, - C0E7A139211A2F6600711656 /* ffmpeg-ios-static-libs */, C0137605211A06080046020A /* essentia */, ); path = libs; @@ -2528,7 +2491,6 @@ C088C988211B561C009ED9DB /* ape */ = { isa = PBXGroup; children = ( - C088C989211B561C009ED9DB /* ape-tag-format.txt */, C088C98A211B561C009ED9DB /* apefile.cpp */, C088C98B211B561C009ED9DB /* apefile.h */, C088C98C211B561C009ED9DB /* apefooter.cpp */, @@ -2668,10 +2630,6 @@ isa = PBXGroup; children = ( C088C9D8211B561C009ED9DB /* frames */, - C088C9FB211B561C009ED9DB /* id3v2.2.0.txt */, - C088C9FC211B561C009ED9DB /* id3v2.3.0.txt */, - C088C9FD211B561C009ED9DB /* id3v2.4.0-frames.txt */, - C088C9FE211B561C009ED9DB /* id3v2.4.0-structure.txt */, C088C9FF211B561C009ED9DB /* id3v2extendedheader.cpp */, C088CA00211B561C009ED9DB /* id3v2extendedheader.h */, C088CA01211B561C009ED9DB /* id3v2footer.cpp */, @@ -2912,14 +2870,12 @@ C0B559FD211B27D0007817F6 /* internal */ = { isa = PBXGroup; children = ( - C088C618211B54C3009ED9DB /* taglib_config.h */, - C0B559FE211B27D0007817F6 /* audioloader_ios.cpp */, - C0B559FF211B27D0007817F6 /* audioloader_ios.h */, - C0B55A00211B27D0007817F6 /* essentia_algorithms_reg.cpp */, - C0B55A01211B27D0007817F6 /* ffmpegapi.h */, C0B55A02211B27D0007817F6 /* music_extractor */, + C0B9C2672130A4140029DA6F /* 3rdparty */, + C037276321304F4C00E9C15C /* audioloader_ios.cpp */, + C037276421304F4C00E9C15C /* audioloader_ios.h */, + C0B55A00211B27D0007817F6 /* essentia_algorithms_reg.cpp */, C0B55A05211B27D0007817F6 /* streaming_extractor_music.h */, - C0B55A06211B27D0007817F6 /* version.h */, ); path = internal; sourceTree = ""; @@ -2933,36 +2889,22 @@ path = music_extractor; sourceTree = ""; }; - C0BA3B8C211A31E90038D19F /* Frameworks */ = { - isa = PBXGroup; - children = ( - C0B559F2211B20CB007817F6 /* Accelerate.framework */, - C0B559F0211B20C4007817F6 /* AudioToolbox.framework */, - C0B559EE211B20A9007817F6 /* libz.tbd */, - C0B559EC211B20A2007817F6 /* libbz2.tbd */, - C0B559EA211B2079007817F6 /* libiconv.tbd */, - C0BA3B8D211A31E90038D19F /* libc++.tbd */, - ); - name = Frameworks; - sourceTree = ""; - }; - C0E7A139211A2F6600711656 /* ffmpeg-ios-static-libs */ = { + C0B9C2672130A4140029DA6F /* 3rdparty */ = { isa = PBXGroup; children = ( - C0E7A1A2211A2F6600711656 /* lib */, + C088C618211B54C3009ED9DB /* taglib_config.h */, + C0B55A06211B27D0007817F6 /* version.h */, ); - path = "ffmpeg-ios-static-libs"; + path = 3rdparty; sourceTree = ""; }; - C0E7A1A2211A2F6600711656 /* lib */ = { + C0BA3B8C211A31E90038D19F /* Frameworks */ = { isa = PBXGroup; children = ( - C0E7A1A3211A2F6600711656 /* libavcodec.a */, - C0E7A1A6211A2F6600711656 /* libavformat.a */, - C0E7A1A7211A2F6600711656 /* libavutil.a */, - C0E7A1A8211A2F6600711656 /* libswresample.a */, + C0B559F2211B20CB007817F6 /* Accelerate.framework */, + C0B559F0211B20C4007817F6 /* AudioToolbox.framework */, ); - path = lib; + name = Frameworks; sourceTree = ""; }; C0E7A219211A30FE00711656 /* src */ = { @@ -3048,7 +2990,6 @@ C0137FAC211A060B0046020A /* mfcc.h in Headers */, C0137F4E211A060B0046020A /* bpmrubato.h in Headers */, C0B55A0C211B27D0007817F6 /* extractor_utils.h in Headers */, - C0B55A08211B27D0007817F6 /* audioloader_ios.h in Headers */, C0137FA6211A060B0046020A /* hpcp.h in Headers */, C017D4C2212DD70B003009FE /* poolaggregator.h in Headers */, C017D4AC212DD426003009FE /* instantpower.h in Headers */, @@ -3124,7 +3065,6 @@ C01380E6211A060C0046020A /* phantombuffer.h in Headers */, C088CBCE211B561D009ED9DB /* rifffile.h in Headers */, C0138132211A060C0046020A /* tnt_fortran_array1d_utils.h in Headers */, - C0B55A0A211B27D0007817F6 /* ffmpegapi.h in Headers */, C017D4B6212DD556003009FE /* crest.h in Headers */, C088CB93211B561D009ED9DB /* unknownframe.h in Headers */, C013811C211A060C0046020A /* metadatautils.h in Headers */, @@ -3266,6 +3206,7 @@ C0137FD0211A060B0046020A /* constantq.h in Headers */, C0137FF6211A060B0046020A /* multiplexer.h in Headers */, C0137F56211A060B0046020A /* noveltycurve.h in Headers */, + C037276621304F4D00E9C15C /* audioloader_ios.h in Headers */, C01380FC211A060C0046020A /* asciidag.h in Headers */, C01380EB211A060C0046020A /* sinkproxy.h in Headers */, C0137FCA211A060B0046020A /* bpf.h in Headers */, @@ -3482,11 +3423,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - C088CB99211B561D009ED9DB /* id3v2.3.0.txt in Resources */, - C088CB30211B561C009ED9DB /* ape-tag-format.txt in Resources */, - C088CB98211B561D009ED9DB /* id3v2.2.0.txt in Resources */, - C088CB9B211B561D009ED9DB /* id3v2.4.0-structure.txt in Resources */, - C088CB9A211B561D009ED9DB /* id3v2.4.0-frames.txt in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3582,7 +3518,6 @@ C0137F87211A060B0046020A /* maxtototal.cpp in Sources */, C088CBB1211B561D009ED9DB /* xingheader.cpp in Sources */, C01380BE211A060C0046020A /* debugging.cpp in Sources */, - C0B55A07211B27D0007817F6 /* audioloader_ios.cpp in Sources */, C0137ECD211A060B0046020A /* kiss_fftnd.c in Sources */, C088CB88211B561D009ED9DB /* relativevolumeframe.cpp in Sources */, C088CB49211B561C009ED9DB /* fileref.cpp in Sources */, @@ -3756,6 +3691,7 @@ C0137F7D211A060B0046020A /* tempotapticks.cpp in Sources */, C088CBAA211B561D009ED9DB /* mpegfile.cpp in Sources */, C0137FAD211A060B0046020A /* panning.cpp in Sources */, + C0B9C2662130872E0029DA6F /* audioloader_ios.cpp in Sources */, C088CBD2211B561D009ED9DB /* wavfile.cpp in Sources */, C01380F0211A060C0046020A /* streamingalgorithm.cpp in Sources */, C0137F4F211A060B0046020A /* harmonicbpm.cpp in Sources */, @@ -3938,6 +3874,11 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + USE_ACCELERATE, + ); HEADER_SEARCH_PATHS = ( "$(SRCROOT)/libs/samplerate/libsamplerate/src", "$(SRCROOT)/libs/ffmpeg-ios-static-libs/include", @@ -3980,6 +3921,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREPROCESSOR_DEFINITIONS = USE_ACCELERATE; HEADER_SEARCH_PATHS = ( "$(SRCROOT)/libs/samplerate/libsamplerate/src", "$(SRCROOT)/libs/ffmpeg-ios-static-libs/include", diff --git a/src/ESExtractor.mm b/src/ESExtractor.mm index c2e6a17..49eddec 100644 --- a/src/ESExtractor.mm +++ b/src/ESExtractor.mm @@ -13,10 +13,12 @@ @implementation ESExtractor - (NSDictionary *)analyseTrack:(NSURL *)url { essentia_main(url.path.UTF8String, [self tempFile].path.UTF8String, ""); - return ({ - NSData* data = [NSData dataWithContentsOfURL:[self tempFile]]; - [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; - }); + NSData* data = [NSData dataWithContentsOfURL:[self tempFile]]; + @try { + return [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; + } @catch (NSException *exception) { + return nil; + } } - (NSURL *)tempFile { diff --git a/src/internal/taglib_config.h b/src/internal/3rdparty/taglib_config.h similarity index 100% rename from src/internal/taglib_config.h rename to src/internal/3rdparty/taglib_config.h diff --git a/src/internal/version.h b/src/internal/3rdparty/version.h similarity index 100% rename from src/internal/version.h rename to src/internal/3rdparty/version.h diff --git a/src/internal/audioloader_ios.cpp b/src/internal/audioloader_ios.cpp index 11fa414..3b1ade1 100644 --- a/src/internal/audioloader_ios.cpp +++ b/src/internal/audioloader_ios.cpp @@ -25,498 +25,217 @@ * version 3 along with this program. If not, see http://www.gnu.org/licenses/ */ + +#include +#include // setw() +#include + #include "audioloader_ios.h" #include "algorithmfactory.h" -#include // setw() using namespace std; -namespace essentia { - namespace streaming { - - const char* AudioLoader::name = essentia::standard::AudioLoader::name; - const char* AudioLoader::category = essentia::standard::AudioLoader::category; - const char* AudioLoader::description = essentia::standard::AudioLoader::description; - - - AudioLoader::~AudioLoader() { - closeAudioFile(); - - av_freep(&_buffer); - av_freep(&_md5Encoded); - av_freep(&_decodedFrame); - } - - void AudioLoader::configure() { - // set ffmpeg to be silent by default, so we don't have these annoying - // "invalid new backstep" messages anymore, when everything is actually fine - av_log_set_level(AV_LOG_QUIET); - //av_log_set_level(AV_LOG_VERBOSE); - _computeMD5 = parameter("computeMD5").toBool(); - _selectedStream = parameter("audioStream").toInt(); - reset(); +string uint8_t_to_hex(uint8_t* input, int size) { + ostringstream result; + for(int i=0; i= nAudioStreams) { - avformat_close_input(&_demuxCtx); - _demuxCtx = 0; - throw EssentiaException("AudioLoader ERROR: 'audioStream' parameter set to ", _selectedStream ,". It should be smaller than the audio streams count, ", nAudioStreams); - } - - _streamIdx = _streams[_selectedStream]; - - // Load corresponding audio codec - _audioCtx = _demuxCtx->streams[_streamIdx]->codec; - _audioCodec = avcodec_find_decoder(_audioCtx->codec_id); - - if (!_audioCodec) { - throw EssentiaException("AudioLoader: Unsupported codec!"); - } - - if (avcodec_open2(_audioCtx, _audioCodec, NULL) < 0) { - throw EssentiaException("AudioLoader: Unable to instantiate codec..."); - } - - // Configure format convertion (no samplerate conversion yet) - int64_t layout = av_get_default_channel_layout(_audioCtx->channels); - - /* - const char* fmt = 0; - get_format_from_sample_fmt(&fmt, _audioCtx->sample_fmt); - E_DEBUG(EAlgorithm, "AudioLoader: converting from " << (fmt ? fmt : "unknown") << " to FLT"); - */ - - E_DEBUG(EAlgorithm, "AudioLoader: using sample format conversion from libavresample"); - -#ifndef TARGET_IOS - _convertCtxAv = avresample_alloc(); -#else - _convertCtxAv = swr_alloc(); -#endif - - av_opt_set_int(_convertCtxAv, "in_channel_layout", layout, 0); - av_opt_set_int(_convertCtxAv, "out_channel_layout", layout, 0); - av_opt_set_int(_convertCtxAv, "in_sample_rate", _audioCtx->sample_rate, 0); - av_opt_set_int(_convertCtxAv, "out_sample_rate", _audioCtx->sample_rate, 0); - av_opt_set_int(_convertCtxAv, "in_sample_fmt", _audioCtx->sample_fmt, 0); - av_opt_set_int(_convertCtxAv, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0); + + // Compute md5 first + if ( parameter("computeMD5").toBool() ) { + CC_MD5_CTX hashObject; -#ifndef TARGET_IOS - if (avresample_open(_convertCtxAv) < 0) { - throw EssentiaException("AudioLoader: Could not initialize avresample context"); + if ( !CC_MD5_Init(&hashObject) ) { + throw EssentiaException("AudioLoader: Error allocating the MD5 context"); } -#else - swr_init(_convertCtxAv); - if (swr_is_initialized(_convertCtxAv) == 0) { - throw EssentiaException("AudioLoader: Could not initialize swresample context"); + AudioFileID file; + if ( AudioFileOpenURL(url, kAudioFileReadPermission, 0, &file) != noErr ) { + throw EssentiaException("AudioLoader: Error reading file for MD5 hash"); } -#endif - - av_init_packet(&_packet); - - _decodedFrame = av_frame_alloc(); - if (!_decodedFrame) { - throw EssentiaException("AudioLoader: Could not allocate audio frame"); + + SInt64 readPos = 0; + UInt32 chunkSize = 4096; + while ( chunkSize == 4096 ) { + void *buffer[chunkSize]; + AudioFileReadBytes(file, false, readPos, &chunkSize, buffer); + CC_MD5_Update(&hashObject, + buffer, + (CC_LONG)chunkSize); + readPos += chunkSize; } - av_md5_init(_md5Encoded); + // Compute the hash digest + unsigned char digest[CC_MD5_DIGEST_LENGTH]; + CC_MD5_Final(digest, &hashObject); + _md5.push(uint8_t_to_hex(digest, 16)); + + } else { + string md5 = ""; + _md5.push(md5); } + } + + void AudioLoader::closeAudioFile() { + if ( _file != NULL ) { + ExtAudioFileDispose( _file ); + _file = NULL; + } + } + + void AudioLoader::pushChannelsSampleRateInfo(int nChannels, Real sampleRate) { + if (nChannels > 2) { + throw EssentiaException("AudioLoader: could not load audio. Audio file has more than 2 channels."); + } + if (sampleRate <= 0) { + throw EssentiaException("AudioLoader: could not load audio. Audio sampling rate must be greater than 0."); + } - void AudioLoader::closeAudioFile() { - if (!_demuxCtx) { - return; - } - -#ifndef TARGET_IOS - if (_convertCtxAv) { - avresample_close(_convertCtxAv); - avresample_free(&_convertCtxAv); - } -#else - if (_convertCtxAv) { - swr_close(_convertCtxAv); - swr_free(&_convertCtxAv); - } -#endif - - // Close the codec - if (_audioCtx) avcodec_close(_audioCtx); - // Close the audio file - if (_demuxCtx) avformat_close_input(&_demuxCtx); - - // free AVPacket - // TODO: use a variable for whether _packet is initialized or not - av_free_packet(&_packet); - _demuxCtx = 0; - _audioCtx = 0; - _streams.clear(); + _channels.push(nChannels); + _sampleRate.push(sampleRate); + } + + void AudioLoader::pushCodecInfo(std::string codec, int bit_rate) { + _codec.push(codec); + _bit_rate.push(bit_rate); + } + + AlgorithmStatus AudioLoader::process() { + if ( !parameter("filename").isConfigured() ) { + throw EssentiaException("AudioLoader: Trying to call process() on an AudioLoader algo which hasn't been correctly configured."); } + AudioStreamBasicDescription audioFormat = {0}; + audioFormat.mFormatID = kAudioFormatLinearPCM; + audioFormat.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved; + audioFormat.mChannelsPerFrame = lastTokenProduced(_channels); + audioFormat.mBytesPerPacket = sizeof(float); + audioFormat.mFramesPerPacket = 1; + audioFormat.mBytesPerFrame = sizeof(float); + audioFormat.mBitsPerChannel = 8 * sizeof(float); + audioFormat.mSampleRate = 44100.0; + + const SInt64 frameCount = 4096; + const UInt32 channels = audioFormat.mChannelsPerFrame; + const UInt32 bytesPerBuffer = audioFormat.mBytesPerFrame * frameCount; + + // Create temporary audio bufferlist + auto bufferList = (AudioBufferList *)malloc(sizeof(AudioBufferList) * channels); + bufferList->mNumberBuffers = channels; + for ( auto i = 0; i < bufferList->mNumberBuffers; i++ ) { + bufferList->mBuffers[i].mNumberChannels = 1; + bufferList->mBuffers[i].mDataByteSize = frameCount * audioFormat.mBytesPerFrame; + bufferList->mBuffers[i].mData = calloc(bytesPerBuffer, 1); + } - void AudioLoader::pushChannelsSampleRateInfo(int nChannels, Real sampleRate) { - if (nChannels > 2) { - throw EssentiaException("AudioLoader: could not load audio. Audio file has more than 2 channels."); - } - if (sampleRate <= 0) { - throw EssentiaException("AudioLoader: could not load audio. Audio sampling rate must be greater than 0."); - } - - _nChannels = nChannels; - - _channels.push(nChannels); - _sampleRate.push(sampleRate); + // Set destination format + if ( ExtAudioFileSetProperty(_file, kExtAudioFileProperty_ClientDataFormat, sizeof(audioFormat), &audioFormat) != noErr ) { + throw EssentiaException("AudioLoader: Error setting client data format"); } + // Read audio + UInt32 readFrames = frameCount; + if ( ExtAudioFileRead(_file, &readFrames, bufferList) != noErr ) { + throw EssentiaException("AudioLoader: Error reading file" ); + } - void AudioLoader::pushCodecInfo(std::string codec, int bit_rate) { - _codec.push(codec); - _bit_rate.push(bit_rate); + // Acquire necessary data + if ( !_audio.acquire(readFrames) ) { + throw EssentiaException("AudioLoader: could not acquire output for audio"); } + auto& audio = *((vector*)_audio.getTokens()); - string uint8_t_to_hex(uint8_t* input, int size) { - ostringstream result; - for(int i=0; imBuffers[1].mData)[i]; + default: + audio[i].left() = ((float *)bufferList->mBuffers[0].mData)[i]; } - return result.str(); } + _audio.release(readFrames); - AlgorithmStatus AudioLoader::process() { - if (!parameter("filename").isConfigured()) { - throw EssentiaException("AudioLoader: Trying to call process() on an AudioLoader algo which hasn't been correctly configured."); - } - - // read frames until we get a good one - do { - int result = av_read_frame(_demuxCtx, &_packet); - //E_DEBUG(EAlgorithm, "AudioLoader: called av_read_frame(), got result = " << result); - if (result != 0) { - // 0 = OK, < 0 = error or EOF - if (result != AVERROR_EOF) { - char errstring[1204]; - av_strerror(result, errstring, sizeof(errstring)); - ostringstream msg; - msg << "AudioLoader: Error reading frame: " << errstring; - E_WARNING(msg.str()); - } - // TODO: should try reading again on EAGAIN error? - // https://github.com/FFmpeg/FFmpeg/blob/master/ffmpeg.c - shouldStop(true); - flushPacket(); - closeAudioFile(); - if (_computeMD5) { - av_md5_final(_md5Encoded, _checksum); - _md5.push(uint8_t_to_hex(_checksum, 16)); - } - else { - string md5 = ""; - _md5.push(md5); - } - return FINISHED; - } - } while (_packet.stream_index != _streamIdx); - - // compute md5 first - if (_computeMD5) { - av_md5_update(_md5Encoded, _packet.data, _packet.size); - } - - // decode frames in packet - while(_packet.size > 0) { - if (!decodePacket()) break; - copyFFmpegOutput(); - } - // neds to be freed !! - av_free_packet(&_packet); - - return OK; + // Free bufferlist + for ( auto i = 0; i < bufferList->mNumberBuffers; i++ ) { + free(bufferList->mBuffers[i].mData); } + free(bufferList); - - int AudioLoader::decode_audio_frame(AVCodecContext* audioCtx, - float* output, - int* outputSize, - AVPacket* packet) { - - // _dataSize input = number of bytes available for write in buff - // output = number of bytes actually written (actual: FLT data) - //E_DEBUG(EAlgorithm, "decode_audio_frame, available bytes in buffer = " << _dataSize); - int gotFrame = 0; - av_frame_unref(_decodedFrame); //avcodec_get_frame_defaults(_decodedFrame); - - int len = avcodec_decode_audio4(audioCtx, _decodedFrame, &gotFrame, packet); - - if (len < 0) return len; // error handling should be done outside + if ( readFrames < frameCount /* EOF */ ) { + shouldStop(true); - if (gotFrame) { - int inputSamples = _decodedFrame->nb_samples; - int inputPlaneSize = av_samples_get_buffer_size(NULL, _nChannels, inputSamples, - audioCtx->sample_fmt, 1); - int outputPlaneSize = av_samples_get_buffer_size(NULL, _nChannels, inputSamples, - AV_SAMPLE_FMT_FLT, 1); - // the size of the output buffer in samples - int outputBufferSamples = *outputSize / - (av_get_bytes_per_sample(AV_SAMPLE_FMT_FLT) * _nChannels); - - if (outputBufferSamples < inputSamples) { - // this should never happen, throw exception here - throw EssentiaException("AudioLoader: Insufficient buffer size for format conversion"); - } - - if (audioCtx->sample_fmt == AV_SAMPLE_FMT_FLT) { - // TODO: no need in this check? Not many of common formats support FLT - // no conversion needed, direct copy from our frame to output buffer - memcpy(output, _decodedFrame->data[0], inputPlaneSize); - } - else { -#ifndef TARGET_IOS - int samplesWrittern = avresample_convert(_convertCtxAv, - (uint8_t**) &output, - outputPlaneSize, - outputBufferSamples, - (uint8_t**)_decodedFrame->data, - inputPlaneSize, - inputSamples); -#else - int samplesWrittern = swr_convert(_convertCtxAv, - (uint8_t**)&output, - outputBufferSamples, - (const uint8_t**)_decodedFrame->data, - inputSamples); -#endif - - if (samplesWrittern < inputSamples) { - // TODO: there may be data remaining in the internal FIFO buffer - // to get this data: call avresample_convert() with NULL input - // Test if this happens in practice - ostringstream msg; - msg << "AudioLoader: Incomplete format conversion (some samples missing)" - << " from " << av_get_sample_fmt_name(_audioCtx->sample_fmt) - << " to " << av_get_sample_fmt_name(AV_SAMPLE_FMT_FLT); - throw EssentiaException(msg); - } - } - *outputSize = outputPlaneSize; - } - else { - E_DEBUG(EAlgorithm, "AudioLoader: tried to decode packet but didn't get any frame..."); - *outputSize = 0; - } - - return len; + return FINISHED; } + + return OK; + } + + void AudioLoader::reset() { + Algorithm::reset(); + if ( !parameter("filename").isConfigured() ) return; - void AudioLoader::flushPacket() { - AVPacket empty; - av_init_packet(&empty); - do { - _dataSize = FFMPEG_BUFFER_SIZE; - empty.data = NULL; - empty.size = 0; - - int len = decode_audio_frame(_audioCtx, _buffer, &_dataSize, &empty); - if (len < 0) { - char errstring[1204]; - av_strerror(len, errstring, sizeof(errstring)); - ostringstream msg; - msg << "AudioLoader: decoding error while flushing a packet:" << errstring; - E_WARNING(msg.str()); - } - copyFFmpegOutput(); - - } while (_dataSize > 0); - } + string filename = parameter("filename").toString(); + closeAudioFile(); + openAudioFile(filename); - /** - * Gets the AVPacket stored in _packet, and decodes all the samples it can from it, - * putting them in _buffer, the total number of bytes written begin stored in _dataSize. - */ - int AudioLoader::decodePacket() { - /* - E_DEBUG(EAlgorithm, "-----------------------------------------------------"); - E_DEBUG(EAlgorithm, "decoding packet of " << _packet.size << " bytes"); - E_DEBUG(EAlgorithm, "pts: " << _packet.pts << " - dts: " << _packet.dts); //" - pos: " << pkt->pos); - E_DEBUG(EAlgorithm, "flags: " << _packet.flags); - E_DEBUG(EAlgorithm, "duration: " << _packet.duration); - */ - int len = 0; - - // buff is an offset in our output buffer, it points to where we should start - // writing the next decoded samples - float* buff = _buffer; - - // _dataSize gets the size of the buffer, in bytes - _dataSize = FFMPEG_BUFFER_SIZE; - - // Note: md5 should be computed before decoding frame, as the decoding may - // change the content of a packet. Still, not sure if it is correct to - // compute md5 over packet which contains incorrect frames, potentially - // belonging to id3 metadata (TODO: or is it just a missing header issue?), - // but computing md5 hash using ffmpeg will also treat it as audio: - // ffmpeg -i file.mp3 -acodec copy -f md5 - - - len = decode_audio_frame(_audioCtx, buff, &_dataSize, &_packet); - - if (len < 0) { - char errstring[1204]; - av_strerror(len, errstring, sizeof(errstring)); - ostringstream msg; - - if (_audioCtx->codec_id == AV_CODEC_ID_MP3) { - msg << "AudioLoader: invalid frame, skipping it: " << errstring; - // mp3 streams can have tag frames (id3v2?) which libavcodec tries to - // read as audio anyway, and we probably don't want print an error - // message for that... - // TODO: Are these frames really id3 tags? - - //E_DEBUG(EAlgorithm, msg); - E_WARNING(msg.str()); - } - else { - msg << "AudioLoader: error while decoding, skipping frame: " << errstring; - E_WARNING(msg.str()); - } - return 0; - } - - if (len != _packet.size) { - // https://www.ffmpeg.org/doxygen/trunk/group__lavc__decoding.html#ga834bb1b062fbcc2de4cf7fb93f154a3e - - // Some decoders may support multiple frames in a single AVPacket. Such - // decoders would then just decode the first frame and the return value - // would be less than the packet size. In this case, avcodec_decode_audio4 - // has to be called again with an AVPacket containing the remaining data - // in order to decode the second frame, etc... Even if no frames are - // returned, the packet needs to be fed to the decoder with remaining - // data until it is completely consumed or an error occurs. - - E_WARNING("AudioLoader: more than 1 frame in packet, decoding remaining bytes..."); - E_WARNING("at sample index: " << output("audio").totalProduced()); - E_WARNING("decoded samples: " << len); - E_WARNING("packet size: " << _packet.size); - } - - // update packet data pointer to data left undecoded (if any) - _packet.size -= len; - _packet.data += len; - - - if (_dataSize <= 0) { - // No data yet, get more frames - // cout << "no data yet, get more frames" << endl; - _dataSize = 0; - } - - return len; + // Get audio file data format + AudioStreamBasicDescription asbd = {0}; + UInt32 propertySize = sizeof(asbd); + if ( ExtAudioFileGetProperty(_file, kExtAudioFileProperty_FileDataFormat, &propertySize, &asbd) != noErr ) { + throw EssentiaException("AudioLoader: Error getting audio file channel and sample rate info"); } + pushChannelsSampleRateInfo(asbd.mChannelsPerFrame, asbd.mSampleRate); - /* - inline Real scale(int16_t value) { - return value / (Real)32767; - } - */ - - void AudioLoader::copyFFmpegOutput() { - int nsamples = _dataSize / (av_get_bytes_per_sample(AV_SAMPLE_FMT_FLT) * _nChannels); - if (nsamples == 0) return; - - // acquire necessary data - bool ok = _audio.acquire(nsamples); - if (!ok) { - throw EssentiaException("AudioLoader: could not acquire output for audio"); - } - - vector& audio = *((vector*)_audio.getTokens()); - - if (_nChannels == 1) { - for (int i=0; ichannels, _audioCtx->sample_rate); - pushCodecInfo(_audioCodec->name, _audioCtx->bit_rate); + UInt32 bitRate = 0; + size = sizeof(bitRate); + if ( AudioFileGetProperty(audioFileId, kAudioFilePropertyBitRate, &size, &bitRate) != noErr ) { + throw EssentiaException("AudioLoader: Error getting audio file bitRate"); } - } // namespace streaming + E_DEBUG(EAlgorithm, "AudioLoader: TODO: get audio codec"); + pushCodecInfo("pcm_s16le", bitRate); + } + +} // namespace streaming } // namespace essentia diff --git a/src/internal/audioloader_ios.h b/src/internal/audioloader_ios.h index 9b83882..85cffea 100755 --- a/src/internal/audioloader_ios.h +++ b/src/internal/audioloader_ios.h @@ -17,27 +17,14 @@ * version 3 along with this program. If not, see http://www.gnu.org/licenses/ */ -#ifndef ESSENTIA_STREAMING_AUDIOLOADER_H -#define ESSENTIA_STREAMING_AUDIOLOADER_H +#pragma once -#if __APPLE__ -#import "TargetConditionals.h" -#endif - -#if (TARGET_OS_IPHONE_SIMULATOR) || (TARGET_OS_IPHONE) || (TARGET_IPHONE) -#define TARGET_IOS -#endif +#include #include "streamingalgorithm.h" #include "network.h" #include "poolstorage.h" -#include "ffmpegapi.h" - -extern AVInputFormat ff_wav_demuxer; - -#define MAX_AUDIO_FRAME_SIZE 192000 - namespace essentia { namespace streaming { @@ -50,37 +37,7 @@ class AudioLoader : public Algorithm { AbsoluteSource _bit_rate; AbsoluteSource _codec; - int _nChannels; - - // MAX_AUDIO_FRAME_SIZE is in bytes, multiply it by 2 to get some margin, - // because we might want to decode multiple frames in this buffer (all the - // frames contained in a packet, which can be more than 1 as in flac), and - // each time we decode a frame we need to have at least a full buffer of free space. - const static int FFMPEG_BUFFER_SIZE = MAX_AUDIO_FRAME_SIZE * 2; - - float* _buffer; - int _dataSize; - - AVFormatContext* _demuxCtx; - AVCodecContext* _audioCtx; - AVCodec* _audioCodec; - AVPacket _packet; - AVMD5 *_md5Encoded; - AVFrame* _decodedFrame; - uint8_t _checksum[16]; - bool _computeMD5; - -#ifndef TARGET_IOS - struct AVAudioResampleContext* _convertCtxAv; -#else - struct SwrContext* _convertCtxAv; -#endif - - int _streamIdx; // index of the audio stream among all the streams contained in the file - std::vector _streams; - int _selectedStream; - bool _configured; - + ExtAudioFileRef _file; void openAudioFile(const std::string& filename); void closeAudioFile(); @@ -88,18 +45,8 @@ class AudioLoader : public Algorithm { void pushChannelsSampleRateInfo(int nChannels, Real sampleRate); void pushCodecInfo(std::string codec, int bit_rate); - int decode_audio_frame(AVCodecContext* audioCtx, float* output, - int* outputSize, AVPacket* packet); - - int decodePacket(); - void flushPacket(); - void copyFFmpegOutput(); - - public: - AudioLoader() : Algorithm(), _buffer(0), _demuxCtx(0), - _audioCtx(0), _audioCodec(0), _decodedFrame(0), - _convertCtxAv(0), _configured(false) { + AudioLoader() : Algorithm() { declareOutput(_audio, 1, "audio", "the input audio signal"); declareOutput(_sampleRate, 0, "sampleRate", "the sampling rate of the audio signal [Hz]"); @@ -109,17 +56,6 @@ class AudioLoader : public Algorithm { declareOutput(_codec, 0, "codec", "the codec that is used to decode the input audio"); _audio.setBufferType(BufferUsage::forLargeAudioStream); - - // Register all formats and codecs - av_register_all(); - - // use av_malloc, because we _need_ the buffer to be 16-byte aligned - _buffer = (float*)av_malloc(FFMPEG_BUFFER_SIZE); - - _md5Encoded = av_md5_alloc(); - if (!_md5Encoded) { - throw EssentiaException("Error allocating the MD5 context"); - } } ~AudioLoader(); @@ -144,67 +80,64 @@ class AudioLoader : public Algorithm { } // namespace streaming } // namespace essentia - #include "vectoroutput.h" #include "algorithm.h" namespace essentia { -namespace standard { - -// Standard non-streaming algorithm comes after the streaming one as it -// depends on it -class AudioLoader : public Algorithm { - - protected: - Output > _audio; - Output _sampleRate; - Output _channels; - Output _md5; - Output _bit_rate; - Output _codec; - - streaming::Algorithm* _loader; - streaming::VectorOutput* _audioStorage; - - scheduler::Network* _network; - Pool _pool; - - void createInnerNetwork(); - - public: - AudioLoader() { - declareOutput(_audio, "audio", "the input audio signal"); - declareOutput(_sampleRate, "sampleRate", "the sampling rate of the audio signal [Hz]"); - declareOutput(_channels, "numberChannels", "the number of channels"); - declareOutput(_md5, "md5", "the MD5 checksum of raw undecoded audio payload"); - declareOutput(_bit_rate, "bit_rate", "the bit rate of the input audio, as reported by the decoder codec"); - declareOutput(_codec, "codec", "the codec that is used to decode the input audio"); - - createInnerNetwork(); - } - - ~AudioLoader() { - // NB: this will also delete all the algorithms as the Network took ownership of them - delete _network; - } - - void declareParameters() { - declareParameter("filename", "the name of the file from which to read", "", Parameter::STRING); - declareParameter("computeMD5", "compute the MD5 checksum", "{true,false}", false); - declareParameter("audioStream", "audio stream index to be loaded. Other streams are no taken into account (e.g. if stream 0 is video and 1 is audio use index 0 to access it.)", "[0,inf)", 0); - } - - void configure(); - - void compute(); - void reset(); - - static const char* name; - static const char* category; - static const char* description; -}; - -} // namespace standard + namespace standard { + + // Standard non-streaming algorithm comes after the streaming one as it + // depends on it + class AudioLoader : public Algorithm { + + protected: + Output > _audio; + Output _sampleRate; + Output _channels; + Output _md5; + Output _bit_rate; + Output _codec; + + streaming::Algorithm* _loader; + streaming::VectorOutput* _audioStorage; + + scheduler::Network* _network; + Pool _pool; + + void createInnerNetwork(); + + public: + AudioLoader() { + declareOutput(_audio, "audio", "the input audio signal"); + declareOutput(_sampleRate, "sampleRate", "the sampling rate of the audio signal [Hz]"); + declareOutput(_channels, "numberChannels", "the number of channels"); + declareOutput(_md5, "md5", "the MD5 checksum of raw undecoded audio payload"); + declareOutput(_bit_rate, "bit_rate", "the bit rate of the input audio, as reported by the decoder codec"); + declareOutput(_codec, "codec", "the codec that is used to decode the input audio"); + + createInnerNetwork(); + } + + ~AudioLoader() { + // NB: this will also delete all the algorithms as the Network took ownership of them + delete _network; + } + + void declareParameters() { + declareParameter("filename", "the name of the file from which to read", "", Parameter::STRING); + declareParameter("computeMD5", "compute the MD5 checksum", "{true,false}", false); + declareParameter("audioStream", "audio stream index to be loaded. Other streams are no taken into account (e.g. if stream 0 is video and 1 is audio use index 0 to access it.)", "[0,inf)", 0); + } + + void configure(); + + void compute(); + void reset(); + + static const char* name; + static const char* category; + static const char* description; + }; + + } // namespace standard } // namespace essentia - -#endif // ESSENTIA_STREAMING_AUDIOLOADER_H diff --git a/src/internal/essentia_algorithms_reg.cpp b/src/internal/essentia_algorithms_reg.cpp index 0a7272c..fc753f3 100644 --- a/src/internal/essentia_algorithms_reg.cpp +++ b/src/internal/essentia_algorithms_reg.cpp @@ -148,13 +148,13 @@ #include "algorithms/temporal/duration.h" #include "algorithms/standard/cubicspline.h" #include "algorithms/extractor/musicextractor.h" -#include "algorithms/io/audioloader.h" #include "algorithms/io/easyloader.h" #include "algorithms/io/eqloudloader.h" #include "algorithms/io/monoloader.h" #include "algorithms/io/metadatareader.h" #include "algorithms/io/yamloutput.h" #include "algorithms/standard/resample.h" +#include "audioloader_ios.h" namespace essentia { namespace standard { diff --git a/src/internal/ffmpegapi.h b/src/internal/ffmpegapi.h deleted file mode 100644 index 9e53302..0000000 --- a/src/internal/ffmpegapi.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2006-2016 Music Technology Group - Universitat Pompeu Fabra - * - * This file is part of Essentia - * - * Essentia is free software: you can redistribute it and/or modify it under - * the terms of the GNU Affero General Public License as published by the Free - * Software Foundation (FSF), either version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the Affero GNU General Public License - * version 3 along with this program. If not, see http://www.gnu.org/licenses/ - */ - -#ifndef ESSENTIA_FFMPEGAPI_H -#define ESSENTIA_FFMPEGAPI_H - -extern "C" { -#include -#include -#include -#include -#include -} - - -// --- from audiocontext - -#ifndef AV_PKT_FLAG_KEY -# define AV_PKT_FLAG_KEY PKT_FLAG_KEY -#endif - -#ifndef AVIO_FLAG_WRITE -# define AVIO_FLAG_WRITE URL_WRONLY -# define avio_open url_fopen -# define avio_close url_fclose -# define avformat_write_header(c, o) av_write_header(c) -#endif - - -#endif // ESSENTIA_FFMPEGAPI_H -