├── .bartycrouch.toml ├── .gitignore ├── Cartfile ├── CoreAudioConverter.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── swiftpm │ │ └── Package.resolved ├── xcshareddata │ ├── xcbaselines │ │ └── F478E1AA1C7D2E8D00670966.xcbaseline │ │ │ ├── F6BD7D74-226C-46E5-9E25-997D3E7DF5FD.plist │ │ │ └── Info.plist │ └── xcschemes │ │ └── CoreAudioConverter macOS.xcscheme └── xcuserdata │ └── Simon.xcuserdatad │ └── xcschemes │ ├── CoreAudioConverter.xcscheme │ └── xcschememanagement.plist ├── CoreAudioConverter ├── Base.lproj │ └── Localizable.strings ├── CACDebug.m ├── CACError.h ├── CACError.m ├── Categories │ ├── NSError+Exceptions.h │ ├── NSError+Exceptions.m │ ├── NSFileManager+FileAccess.h │ ├── NSFileManager+FileAccess.m │ ├── NSImage+PNGData.h │ └── NSImage+PNGData.m ├── CoreAudioConverter.h ├── Decode │ ├── CADecoder.h │ └── CADecoder.m ├── Encode │ ├── EncoderTask.h │ ├── EncoderTask.m │ ├── MP3Encoder.h │ ├── MP3Encoder.m │ └── MP3EncoderDelegateProtocol.h ├── Info.plist ├── Utility │ ├── CACDebug.h │ ├── CircularBuffer.h │ └── CircularBuffer.m ├── de.lproj │ └── Localizable.strings ├── en.lproj │ └── Localizable.strings └── fr.lproj │ └── Localizable.strings ├── Integration Test ├── Info.plist ├── MP3EncondingTests.m ├── test-files │ ├── AAC 44.100 Hz Stereo 320 kbits:s.m4a │ ├── AAC 44.100 Hz Stereo 80 kbits:s (HE).m4a │ ├── AIFF (Linear PCM 16 Bit Big Endian Ganzzahl mit Vorzeichen).aiff │ ├── AIFF (Linear PCM 24 Bit Big Endian Ganzzahl mit Vorzeichen).aiff │ ├── AIFF (Linear PCM 8 Bit Ganzzahl mit Vorzeichen).aiff │ ├── AIFF 44100 Hz Stereo 16 Bit.aif │ ├── Apple Lossless.m4a │ ├── Apple MPEG-4-Audio (AAC).m4a │ ├── WAV Microsoft (Signed 16 bit PCM).wav │ ├── about.rtf │ ├── test-cover.jpg │ ├── wrong_data.m4a │ └── wrong_filetype.wma └── test-files_backup │ ├── AAC 44.100 Hz Stereo 320 kbits:s.m4a │ ├── AAC 44.100 Hz Stereo 80 kbits:s (HE).m4a │ ├── AIFF (Linear PCM 16 Bit Big Endian Ganzzahl mit Vorzeichen).aiff │ ├── AIFF (Linear PCM 24 Bit Big Endian Ganzzahl mit Vorzeichen).aiff │ ├── AIFF (Linear PCM 8 Bit Ganzzahl mit Vorzeichen).aiff │ ├── AIFF 44100 Hz Stereo 16 Bit.aif │ ├── Apple Lossless.m4a │ ├── Apple MPEG-4-Audio (AAC).m4a │ ├── about.rtf │ └── test-cover.jpg ├── LICENSE ├── OptimizationProfiles └── CoreAudioConverter.profdata └── README.md /.bartycrouch.toml: -------------------------------------------------------------------------------- 1 | [update] 2 | tasks = ["code"] 3 | 4 | [update.code] 5 | codePath = "CoreAudioConverter/" 6 | localizablePath = "." 7 | defaultToKeys = false 8 | additive = true 9 | unstripped = false 10 | 11 | [update.transform] 12 | codePath = "." 13 | localizablePath = "." 14 | transformer = "foundation" 15 | supportedLanguageEnumPath = "." 16 | typeName = "BartyCrouch" 17 | translateMethodName = "translate" 18 | 19 | [lint] 20 | path = "." 21 | duplicateKeys = true 22 | emptyValues = true 23 | exclude = [".git/", "Carthage/", "Integration Test/"] 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/xcode,macos,swift,objective-c 2 | # Edit at https://www.gitignore.io/?templates=xcode,macos,swift,objective-c 3 | 4 | ### macOS ### 5 | # General 6 | .DS_Store 7 | .AppleDouble 8 | .LSOverride 9 | 10 | # Icon must end with two \r 11 | Icon 12 | 13 | # Thumbnails 14 | ._* 15 | 16 | # Files that might appear in the root of a volume 17 | .DocumentRevisions-V100 18 | .fseventsd 19 | .Spotlight-V100 20 | .TemporaryItems 21 | .Trashes 22 | .VolumeIcon.icns 23 | .com.apple.timemachine.donotpresent 24 | 25 | # Directories potentially created on remote AFP share 26 | .AppleDB 27 | .AppleDesktop 28 | Network Trash Folder 29 | Temporary Items 30 | .apdisk 31 | 32 | ### Objective-C ### 33 | # Xcode 34 | # 35 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 36 | 37 | ## Build generated 38 | build/ 39 | DerivedData/ 40 | 41 | ## Various settings 42 | *.pbxuser 43 | !default.pbxuser 44 | *.mode1v3 45 | !default.mode1v3 46 | *.mode2v3 47 | !default.mode2v3 48 | *.perspectivev3 49 | !default.perspectivev3 50 | xcuserdata/ 51 | 52 | ## Other 53 | *.moved-aside 54 | *.xccheckout 55 | *.xcscmblueprint 56 | 57 | ## Obj-C/Swift specific 58 | *.hmap 59 | *.ipa 60 | *.dSYM.zip 61 | *.dSYM 62 | 63 | # CocoaPods 64 | # We recommend against adding the Pods directory to your .gitignore. However 65 | # you should judge for yourself, the pros and cons are mentioned at: 66 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 67 | # Pods/ 68 | # Add this line if you want to avoid checking in source code from the Xcode workspace 69 | # *.xcworkspace 70 | 71 | # Carthage 72 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 73 | # Carthage/Checkouts 74 | 75 | Carthage 76 | Cartfile.resolved 77 | 78 | # fastlane 79 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 80 | # screenshots whenever they are needed. 81 | # For more information about the recommended setup visit: 82 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 83 | 84 | fastlane/report.xml 85 | fastlane/Preview.html 86 | fastlane/screenshots/**/*.png 87 | fastlane/test_output 88 | 89 | # Code Injection 90 | # After new code Injection tools there's a generated folder /iOSInjectionProject 91 | # https://github.com/johnno1962/injectionforxcode 92 | 93 | iOSInjectionProject/ 94 | 95 | ### Objective-C Patch ### 96 | 97 | ### Swift ### 98 | # Xcode 99 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 100 | 101 | 102 | 103 | 104 | 105 | ## Playgrounds 106 | timeline.xctimeline 107 | playground.xcworkspace 108 | 109 | # Swift Package Manager 110 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 111 | # Packages/ 112 | # Package.pins 113 | # Package.resolved 114 | .build/ 115 | 116 | # CocoaPods 117 | # We recommend against adding the Pods directory to your .gitignore. However 118 | # you should judge for yourself, the pros and cons are mentioned at: 119 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 120 | # Pods/ 121 | # Add this line if you want to avoid checking in source code from the Xcode workspace 122 | # *.xcworkspace 123 | 124 | # Carthage 125 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 126 | # Carthage/Checkouts 127 | 128 | 129 | # fastlane 130 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 131 | # screenshots whenever they are needed. 132 | # For more information about the recommended setup visit: 133 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 134 | 135 | 136 | # Code Injection 137 | # After new code Injection tools there's a generated folder /iOSInjectionProject 138 | # https://github.com/johnno1962/injectionforxcode 139 | 140 | 141 | ### Xcode ### 142 | # Xcode 143 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 144 | 145 | ## User settings 146 | 147 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 148 | 149 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 150 | 151 | # End of https://www.gitignore.io/api/xcode,macos,swift,objective-c 152 | 153 | -------------------------------------------------------------------------------- /Cartfile: -------------------------------------------------------------------------------- 1 | github "Phisto/AudioFileTagger" ~> 1.0 2 | -------------------------------------------------------------------------------- /CoreAudioConverter.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXAggregateTarget section */ 10 | F47CAFD71D91454400CFAB41 /* Documentation */ = { 11 | isa = PBXAggregateTarget; 12 | buildConfigurationList = F47CAFDE1D91454400CFAB41 /* Build configuration list for PBXAggregateTarget "Documentation" */; 13 | buildPhases = ( 14 | F47CAFDF1D91454A00CFAB41 /* ShellScript */, 15 | ); 16 | dependencies = ( 17 | ); 18 | name = Documentation; 19 | productName = Documentation; 20 | }; 21 | /* End PBXAggregateTarget section */ 22 | 23 | /* Begin PBXBuildFile section */ 24 | 4A24129923A4E7D600B43215 /* CACDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A24129723A4E7D600B43215 /* CACDebug.h */; }; 25 | 4A24129A23A4E7D600B43215 /* CACDebug.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A24129823A4E7D600B43215 /* CACDebug.m */; }; 26 | 4A874B6D24AA9002001E648A /* AudioFileTagger.framework in Copy Dependent Frameworks */ = {isa = PBXBuildFile; fileRef = 4AC69CD823A54BF3008E0532 /* AudioFileTagger.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 27 | 4A874B6F24AA90BF001E648A /* TagLib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A874B6E24AA90B0001E648A /* TagLib.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 28 | 4A874B7224AA9105001E648A /* TagLib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A874B6E24AA90B0001E648A /* TagLib.framework */; }; 29 | 4A874B7424AA9114001E648A /* AudioFileTagger.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4AC69CD823A54BF3008E0532 /* AudioFileTagger.framework */; }; 30 | 4A874B7524AA912A001E648A /* TagLib.framework in Copy Dependent Frameworks */ = {isa = PBXBuildFile; fileRef = 4A874B6E24AA90B0001E648A /* TagLib.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 31 | 4AC69CD923A54BF3008E0532 /* AudioFileTagger.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4AC69CD823A54BF3008E0532 /* AudioFileTagger.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 32 | 4AD749502ADE0C81006F48EB /* lame in Frameworks */ = {isa = PBXBuildFile; productRef = 4AD7494F2ADE0C81006F48EB /* lame */; }; 33 | F40F2A681CA99DE900BDCF2B /* MP3EncondingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F40F2A671CA99DE900BDCF2B /* MP3EncondingTests.m */; }; 34 | F40F2A761CA99E0B00BDCF2B /* test-cover.jpg in Resources */ = {isa = PBXBuildFile; fileRef = F40F2A6C1CA99E0B00BDCF2B /* test-cover.jpg */; }; 35 | F40F2A771CA99E0B00BDCF2B /* Apple MPEG-4-Audio (AAC).m4a in Resources */ = {isa = PBXBuildFile; fileRef = F40F2A6D1CA99E0B00BDCF2B /* Apple MPEG-4-Audio (AAC).m4a */; }; 36 | F40F2A781CA99E0B00BDCF2B /* Apple Lossless.m4a in Resources */ = {isa = PBXBuildFile; fileRef = F40F2A6E1CA99E0B00BDCF2B /* Apple Lossless.m4a */; }; 37 | F40F2A791CA99E0B00BDCF2B /* AIFF 44100 Hz Stereo 16 Bit.aif in Resources */ = {isa = PBXBuildFile; fileRef = F40F2A6F1CA99E0B00BDCF2B /* AIFF 44100 Hz Stereo 16 Bit.aif */; }; 38 | F40F2A7A1CA99E0B00BDCF2B /* AIFF (Linear PCM 24 Bit Big Endian Ganzzahl mit Vorzeichen).aiff in Resources */ = {isa = PBXBuildFile; fileRef = F40F2A701CA99E0B00BDCF2B /* AIFF (Linear PCM 24 Bit Big Endian Ganzzahl mit Vorzeichen).aiff */; }; 39 | F40F2A7B1CA99E0B00BDCF2B /* AIFF (Linear PCM 16 Bit Big Endian Ganzzahl mit Vorzeichen).aiff in Resources */ = {isa = PBXBuildFile; fileRef = F40F2A711CA99E0B00BDCF2B /* AIFF (Linear PCM 16 Bit Big Endian Ganzzahl mit Vorzeichen).aiff */; }; 40 | F40F2A7C1CA99E0B00BDCF2B /* AIFF (Linear PCM 8 Bit Ganzzahl mit Vorzeichen).aiff in Resources */ = {isa = PBXBuildFile; fileRef = F40F2A721CA99E0B00BDCF2B /* AIFF (Linear PCM 8 Bit Ganzzahl mit Vorzeichen).aiff */; }; 41 | F40F2A7D1CA99E0B00BDCF2B /* about.rtf in Resources */ = {isa = PBXBuildFile; fileRef = F40F2A731CA99E0B00BDCF2B /* about.rtf */; }; 42 | F40F2A7E1CA99E0B00BDCF2B /* AAC 44.100 Hz Stereo 320 kbits:s.m4a in Resources */ = {isa = PBXBuildFile; fileRef = F40F2A741CA99E0B00BDCF2B /* AAC 44.100 Hz Stereo 320 kbits:s.m4a */; }; 43 | F40F2A7F1CA99E0B00BDCF2B /* AAC 44.100 Hz Stereo 80 kbits:s (HE).m4a in Resources */ = {isa = PBXBuildFile; fileRef = F40F2A751CA99E0B00BDCF2B /* AAC 44.100 Hz Stereo 80 kbits:s (HE).m4a */; }; 44 | F44BC1311D7986B4008D9CF1 /* NSFileManager+FileAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = F44BC12F1D7986B4008D9CF1 /* NSFileManager+FileAccess.h */; }; 45 | F44BC1321D7986B4008D9CF1 /* NSFileManager+FileAccess.m in Sources */ = {isa = PBXBuildFile; fileRef = F44BC1301D7986B4008D9CF1 /* NSFileManager+FileAccess.m */; }; 46 | F45155561D5F6E9200B6FDEF /* EncoderTask.h in Headers */ = {isa = PBXBuildFile; fileRef = F45155541D5F6E9200B6FDEF /* EncoderTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; 47 | F45155571D5F6E9200B6FDEF /* EncoderTask.m in Sources */ = {isa = PBXBuildFile; fileRef = F45155551D5F6E9200B6FDEF /* EncoderTask.m */; }; 48 | F4727BA71D478EA200B15C13 /* MP3Encoder.m in Sources */ = {isa = PBXBuildFile; fileRef = F4727BA51D478EA200B15C13 /* MP3Encoder.m */; }; 49 | F4727BA81D478EA200B15C13 /* MP3Encoder.h in Headers */ = {isa = PBXBuildFile; fileRef = F4727BA61D478EA200B15C13 /* MP3Encoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; 50 | F474F08E1D55154E007BF84D /* NSError+Exceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = F474F08C1D55154E007BF84D /* NSError+Exceptions.h */; }; 51 | F474F08F1D55154E007BF84D /* NSError+Exceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = F474F08D1D55154E007BF84D /* NSError+Exceptions.m */; }; 52 | F47CAFE71D9154BA00CFAB41 /* MP3EncoderDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F47CAFE51D9154BA00CFAB41 /* MP3EncoderDelegateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 53 | F49DF7DC1BAF8D63003A7C41 /* CoreAudioConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = F49DF7DB1BAF8D63003A7C41 /* CoreAudioConverter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 54 | F49DF8051BAF93DB003A7C41 /* CircularBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = F49DF8011BAF93DB003A7C41 /* CircularBuffer.h */; }; 55 | F49DF8061BAF93DB003A7C41 /* CircularBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = F49DF8021BAF93DB003A7C41 /* CircularBuffer.m */; }; 56 | F49DF8091BAF93ED003A7C41 /* CADecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = F49DF8071BAF93ED003A7C41 /* CADecoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; 57 | F49DF80A1BAF93ED003A7C41 /* CADecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = F49DF8081BAF93ED003A7C41 /* CADecoder.m */; }; 58 | F4CE0C621D5C6FF3009360C6 /* CoreAudioConverter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F49DF7D81BAF8D63003A7C41 /* CoreAudioConverter.framework */; }; 59 | F4CE0C711D5C7AB7009360C6 /* WAV Microsoft (Signed 16 bit PCM).wav in Resources */ = {isa = PBXBuildFile; fileRef = F4CE0C701D5C7AB7009360C6 /* WAV Microsoft (Signed 16 bit PCM).wav */; }; 60 | F4CE0C741D5C7D55009360C6 /* wrong_data.m4a in Resources */ = {isa = PBXBuildFile; fileRef = F4CE0C721D5C7D55009360C6 /* wrong_data.m4a */; }; 61 | F4CE0C751D5C7D55009360C6 /* wrong_filetype.wma in Resources */ = {isa = PBXBuildFile; fileRef = F4CE0C731D5C7D55009360C6 /* wrong_filetype.wma */; }; 62 | F4D917E1222D641500D4A594 /* CACError.h in Headers */ = {isa = PBXBuildFile; fileRef = F4D917DF222D641500D4A594 /* CACError.h */; }; 63 | F4D917E2222D641500D4A594 /* CACError.m in Sources */ = {isa = PBXBuildFile; fileRef = F4D917E0222D641500D4A594 /* CACError.m */; }; 64 | /* End PBXBuildFile section */ 65 | 66 | /* Begin PBXContainerItemProxy section */ 67 | F408FEE61D52704000440412 /* PBXContainerItemProxy */ = { 68 | isa = PBXContainerItemProxy; 69 | containerPortal = F49DF7CF1BAF8D63003A7C41 /* Project object */; 70 | proxyType = 1; 71 | remoteGlobalIDString = F49DF7D71BAF8D63003A7C41; 72 | remoteInfo = CoreAudioConverter; 73 | }; 74 | /* End PBXContainerItemProxy section */ 75 | 76 | /* Begin PBXCopyFilesBuildPhase section */ 77 | 4A874B6B24AA8F3B001E648A /* Copy Dependent Frameworks */ = { 78 | isa = PBXCopyFilesBuildPhase; 79 | buildActionMask = 2147483647; 80 | dstPath = ""; 81 | dstSubfolderSpec = 10; 82 | files = ( 83 | 4A874B6D24AA9002001E648A /* AudioFileTagger.framework in Copy Dependent Frameworks */, 84 | 4A874B7524AA912A001E648A /* TagLib.framework in Copy Dependent Frameworks */, 85 | ); 86 | name = "Copy Dependent Frameworks"; 87 | runOnlyForDeploymentPostprocessing = 0; 88 | }; 89 | /* End PBXCopyFilesBuildPhase section */ 90 | 91 | /* Begin PBXFileReference section */ 92 | 4A24129723A4E7D600B43215 /* CACDebug.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CACDebug.h; path = Utility/CACDebug.h; sourceTree = ""; }; 93 | 4A24129823A4E7D600B43215 /* CACDebug.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CACDebug.m; sourceTree = ""; }; 94 | 4A24129C23A4F73000B43215 /* .bartycrouch.toml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .bartycrouch.toml; sourceTree = ""; }; 95 | 4A874B6E24AA90B0001E648A /* TagLib.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TagLib.framework; path = Carthage/Build/Mac/TagLib.framework; sourceTree = ""; }; 96 | 4AC69CD023A53F12008E0532 /* Cartfile */ = {isa = PBXFileReference; lastKnownFileType = text; path = Cartfile; sourceTree = ""; }; 97 | 4AC69CD823A54BF3008E0532 /* AudioFileTagger.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioFileTagger.framework; path = Carthage/Build/Mac/AudioFileTagger.framework; sourceTree = ""; }; 98 | F40F2A671CA99DE900BDCF2B /* MP3EncondingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MP3EncondingTests.m; sourceTree = ""; }; 99 | F40F2A6C1CA99E0B00BDCF2B /* test-cover.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = "test-cover.jpg"; path = "test-files/test-cover.jpg"; sourceTree = ""; }; 100 | F40F2A6D1CA99E0B00BDCF2B /* Apple MPEG-4-Audio (AAC).m4a */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Apple MPEG-4-Audio (AAC).m4a"; path = "test-files/Apple MPEG-4-Audio (AAC).m4a"; sourceTree = ""; }; 101 | F40F2A6E1CA99E0B00BDCF2B /* Apple Lossless.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Apple Lossless.m4a"; path = "test-files/Apple Lossless.m4a"; sourceTree = ""; }; 102 | F40F2A6F1CA99E0B00BDCF2B /* AIFF 44100 Hz Stereo 16 Bit.aif */ = {isa = PBXFileReference; lastKnownFileType = file; name = "AIFF 44100 Hz Stereo 16 Bit.aif"; path = "test-files/AIFF 44100 Hz Stereo 16 Bit.aif"; sourceTree = ""; }; 103 | F40F2A701CA99E0B00BDCF2B /* AIFF (Linear PCM 24 Bit Big Endian Ganzzahl mit Vorzeichen).aiff */ = {isa = PBXFileReference; lastKnownFileType = audio.aiff; name = "AIFF (Linear PCM 24 Bit Big Endian Ganzzahl mit Vorzeichen).aiff"; path = "test-files/AIFF (Linear PCM 24 Bit Big Endian Ganzzahl mit Vorzeichen).aiff"; sourceTree = ""; }; 104 | F40F2A711CA99E0B00BDCF2B /* AIFF (Linear PCM 16 Bit Big Endian Ganzzahl mit Vorzeichen).aiff */ = {isa = PBXFileReference; lastKnownFileType = audio.aiff; name = "AIFF (Linear PCM 16 Bit Big Endian Ganzzahl mit Vorzeichen).aiff"; path = "test-files/AIFF (Linear PCM 16 Bit Big Endian Ganzzahl mit Vorzeichen).aiff"; sourceTree = ""; }; 105 | F40F2A721CA99E0B00BDCF2B /* AIFF (Linear PCM 8 Bit Ganzzahl mit Vorzeichen).aiff */ = {isa = PBXFileReference; lastKnownFileType = audio.aiff; name = "AIFF (Linear PCM 8 Bit Ganzzahl mit Vorzeichen).aiff"; path = "test-files/AIFF (Linear PCM 8 Bit Ganzzahl mit Vorzeichen).aiff"; sourceTree = ""; }; 106 | F40F2A731CA99E0B00BDCF2B /* about.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; name = about.rtf; path = "test-files/about.rtf"; sourceTree = ""; }; 107 | F40F2A741CA99E0B00BDCF2B /* AAC 44.100 Hz Stereo 320 kbits:s.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; name = "AAC 44.100 Hz Stereo 320 kbits:s.m4a"; path = "test-files/AAC 44.100 Hz Stereo 320 kbits:s.m4a"; sourceTree = ""; }; 108 | F40F2A751CA99E0B00BDCF2B /* AAC 44.100 Hz Stereo 80 kbits:s (HE).m4a */ = {isa = PBXFileReference; lastKnownFileType = file; name = "AAC 44.100 Hz Stereo 80 kbits:s (HE).m4a"; path = "test-files/AAC 44.100 Hz Stereo 80 kbits:s (HE).m4a"; sourceTree = ""; }; 109 | F44BC12F1D7986B4008D9CF1 /* NSFileManager+FileAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSFileManager+FileAccess.h"; path = "Categories/NSFileManager+FileAccess.h"; sourceTree = ""; }; 110 | F44BC1301D7986B4008D9CF1 /* NSFileManager+FileAccess.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSFileManager+FileAccess.m"; path = "Categories/NSFileManager+FileAccess.m"; sourceTree = ""; }; 111 | F45155541D5F6E9200B6FDEF /* EncoderTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EncoderTask.h; sourceTree = ""; }; 112 | F45155551D5F6E9200B6FDEF /* EncoderTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EncoderTask.m; sourceTree = ""; }; 113 | F4727BA51D478EA200B15C13 /* MP3Encoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MP3Encoder.m; sourceTree = ""; }; 114 | F4727BA61D478EA200B15C13 /* MP3Encoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MP3Encoder.h; sourceTree = ""; }; 115 | F474F08C1D55154E007BF84D /* NSError+Exceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSError+Exceptions.h"; path = "Categories/NSError+Exceptions.h"; sourceTree = ""; }; 116 | F474F08D1D55154E007BF84D /* NSError+Exceptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSError+Exceptions.m"; path = "Categories/NSError+Exceptions.m"; sourceTree = ""; }; 117 | F478E19C1C7D249C00670966 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = CoreAudioConverter/fr.lproj/Localizable.strings; sourceTree = ""; }; 118 | F478E19F1C7D249C00670966 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = CoreAudioConverter/en.lproj/Localizable.strings; sourceTree = ""; }; 119 | F478E1A11C7D249C00670966 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = CoreAudioConverter/de.lproj/Localizable.strings; sourceTree = ""; }; 120 | F478E1A51C7D24B100670966 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = CoreAudioConverter/Base.lproj/Localizable.strings; sourceTree = ""; }; 121 | F478E1AB1C7D2E8D00670966 /* CoreAudioConverterTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreAudioConverterTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 122 | F478E1AF1C7D2E8D00670966 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 123 | F47BC41A1DAC468B003DD71F /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; 124 | F47BC41E1DAC4CCB003DD71F /* LICENSE */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = LICENSE; sourceTree = SOURCE_ROOT; }; 125 | F47CAFE51D9154BA00CFAB41 /* MP3EncoderDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MP3EncoderDelegateProtocol.h; sourceTree = ""; }; 126 | F49DF7D81BAF8D63003A7C41 /* CoreAudioConverter.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CoreAudioConverter.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 127 | F49DF7DB1BAF8D63003A7C41 /* CoreAudioConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreAudioConverter.h; sourceTree = ""; }; 128 | F49DF7DD1BAF8D63003A7C41 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 129 | F49DF8011BAF93DB003A7C41 /* CircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CircularBuffer.h; sourceTree = ""; }; 130 | F49DF8021BAF93DB003A7C41 /* CircularBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CircularBuffer.m; sourceTree = ""; }; 131 | F49DF8071BAF93ED003A7C41 /* CADecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CADecoder.h; sourceTree = ""; }; 132 | F49DF8081BAF93ED003A7C41 /* CADecoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CADecoder.m; sourceTree = ""; }; 133 | F4CE0C701D5C7AB7009360C6 /* WAV Microsoft (Signed 16 bit PCM).wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = "WAV Microsoft (Signed 16 bit PCM).wav"; path = "test-files/WAV Microsoft (Signed 16 bit PCM).wav"; sourceTree = ""; }; 134 | F4CE0C721D5C7D55009360C6 /* wrong_data.m4a */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = wrong_data.m4a; path = "test-files/wrong_data.m4a"; sourceTree = ""; }; 135 | F4CE0C731D5C7D55009360C6 /* wrong_filetype.wma */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = wrong_filetype.wma; path = "test-files/wrong_filetype.wma"; sourceTree = ""; }; 136 | F4D917DC222C508700D4A594 /* .gitignore */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = .gitignore; sourceTree = ""; }; 137 | F4D917DF222D641500D4A594 /* CACError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CACError.h; sourceTree = ""; }; 138 | F4D917E0222D641500D4A594 /* CACError.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CACError.m; sourceTree = ""; }; 139 | F4ED6AC41D8F83AC001DB076 /* CoreAudioConverter.profdata */ = {isa = PBXFileReference; lastKnownFileType = file; path = CoreAudioConverter.profdata; sourceTree = ""; }; 140 | /* End PBXFileReference section */ 141 | 142 | /* Begin PBXFrameworksBuildPhase section */ 143 | F478E1A81C7D2E8D00670966 /* Frameworks */ = { 144 | isa = PBXFrameworksBuildPhase; 145 | buildActionMask = 2147483647; 146 | files = ( 147 | F4CE0C621D5C6FF3009360C6 /* CoreAudioConverter.framework in Frameworks */, 148 | 4A874B7424AA9114001E648A /* AudioFileTagger.framework in Frameworks */, 149 | 4A874B7224AA9105001E648A /* TagLib.framework in Frameworks */, 150 | ); 151 | runOnlyForDeploymentPostprocessing = 0; 152 | }; 153 | F49DF7D41BAF8D63003A7C41 /* Frameworks */ = { 154 | isa = PBXFrameworksBuildPhase; 155 | buildActionMask = 2147483647; 156 | files = ( 157 | 4A874B6F24AA90BF001E648A /* TagLib.framework in Frameworks */, 158 | 4AC69CD923A54BF3008E0532 /* AudioFileTagger.framework in Frameworks */, 159 | 4AD749502ADE0C81006F48EB /* lame in Frameworks */, 160 | ); 161 | runOnlyForDeploymentPostprocessing = 0; 162 | }; 163 | /* End PBXFrameworksBuildPhase section */ 164 | 165 | /* Begin PBXGroup section */ 166 | F40F2A6B1CA99DFF00BDCF2B /* test-files */ = { 167 | isa = PBXGroup; 168 | children = ( 169 | F4CE0C721D5C7D55009360C6 /* wrong_data.m4a */, 170 | F4CE0C731D5C7D55009360C6 /* wrong_filetype.wma */, 171 | F4CE0C701D5C7AB7009360C6 /* WAV Microsoft (Signed 16 bit PCM).wav */, 172 | F40F2A6C1CA99E0B00BDCF2B /* test-cover.jpg */, 173 | F40F2A6D1CA99E0B00BDCF2B /* Apple MPEG-4-Audio (AAC).m4a */, 174 | F40F2A6E1CA99E0B00BDCF2B /* Apple Lossless.m4a */, 175 | F40F2A6F1CA99E0B00BDCF2B /* AIFF 44100 Hz Stereo 16 Bit.aif */, 176 | F40F2A701CA99E0B00BDCF2B /* AIFF (Linear PCM 24 Bit Big Endian Ganzzahl mit Vorzeichen).aiff */, 177 | F40F2A711CA99E0B00BDCF2B /* AIFF (Linear PCM 16 Bit Big Endian Ganzzahl mit Vorzeichen).aiff */, 178 | F40F2A721CA99E0B00BDCF2B /* AIFF (Linear PCM 8 Bit Ganzzahl mit Vorzeichen).aiff */, 179 | F40F2A731CA99E0B00BDCF2B /* about.rtf */, 180 | F40F2A741CA99E0B00BDCF2B /* AAC 44.100 Hz Stereo 320 kbits:s.m4a */, 181 | F40F2A751CA99E0B00BDCF2B /* AAC 44.100 Hz Stereo 80 kbits:s (HE).m4a */, 182 | ); 183 | name = "test-files"; 184 | sourceTree = ""; 185 | }; 186 | F474F0901D5516CE007BF84D /* Categories */ = { 187 | isa = PBXGroup; 188 | children = ( 189 | F474F08C1D55154E007BF84D /* NSError+Exceptions.h */, 190 | F474F08D1D55154E007BF84D /* NSError+Exceptions.m */, 191 | F44BC12F1D7986B4008D9CF1 /* NSFileManager+FileAccess.h */, 192 | F44BC1301D7986B4008D9CF1 /* NSFileManager+FileAccess.m */, 193 | ); 194 | name = Categories; 195 | sourceTree = ""; 196 | }; 197 | F478E1991C7D09E100670966 /* OptimizationProfiles */ = { 198 | isa = PBXGroup; 199 | children = ( 200 | F4ED6AC41D8F83AC001DB076 /* CoreAudioConverter.profdata */, 201 | ); 202 | path = OptimizationProfiles; 203 | sourceTree = ""; 204 | }; 205 | F478E1AC1C7D2E8D00670966 /* Integration Test */ = { 206 | isa = PBXGroup; 207 | children = ( 208 | F40F2A6B1CA99DFF00BDCF2B /* test-files */, 209 | F478E1AF1C7D2E8D00670966 /* Info.plist */, 210 | F40F2A671CA99DE900BDCF2B /* MP3EncondingTests.m */, 211 | ); 212 | path = "Integration Test"; 213 | sourceTree = ""; 214 | }; 215 | F49DF7CE1BAF8D63003A7C41 = { 216 | isa = PBXGroup; 217 | children = ( 218 | F49DF7DA1BAF8D63003A7C41 /* CoreAudioConverter */, 219 | F478E1AC1C7D2E8D00670966 /* Integration Test */, 220 | F49DF7D91BAF8D63003A7C41 /* Products */, 221 | F478E1991C7D09E100670966 /* OptimizationProfiles */, 222 | F4ED6ABD1D8F819B001DB076 /* Frameworks */, 223 | F47BC41E1DAC4CCB003DD71F /* LICENSE */, 224 | 4AC69CD023A53F12008E0532 /* Cartfile */, 225 | F47BC41A1DAC468B003DD71F /* README.md */, 226 | 4A24129C23A4F73000B43215 /* .bartycrouch.toml */, 227 | F4D917DC222C508700D4A594 /* .gitignore */, 228 | ); 229 | sourceTree = ""; 230 | }; 231 | F49DF7D91BAF8D63003A7C41 /* Products */ = { 232 | isa = PBXGroup; 233 | children = ( 234 | F49DF7D81BAF8D63003A7C41 /* CoreAudioConverter.framework */, 235 | F478E1AB1C7D2E8D00670966 /* CoreAudioConverterTests.xctest */, 236 | ); 237 | name = Products; 238 | sourceTree = ""; 239 | }; 240 | F49DF7DA1BAF8D63003A7C41 /* CoreAudioConverter */ = { 241 | isa = PBXGroup; 242 | children = ( 243 | F49DF7DB1BAF8D63003A7C41 /* CoreAudioConverter.h */, 244 | F49DF7F91BAF8F35003A7C41 /* Encode */, 245 | F49DF7F71BAF8F17003A7C41 /* Decode */, 246 | F49DF7F81BAF8F25003A7C41 /* Utility */, 247 | F474F0901D5516CE007BF84D /* Categories */, 248 | F4D917DD222D570F00D4A594 /* Other */, 249 | F478E19B1C7D249C00670966 /* Localizable.strings */, 250 | F49DF7DD1BAF8D63003A7C41 /* Info.plist */, 251 | ); 252 | path = CoreAudioConverter; 253 | sourceTree = ""; 254 | }; 255 | F49DF7F71BAF8F17003A7C41 /* Decode */ = { 256 | isa = PBXGroup; 257 | children = ( 258 | F49DF8071BAF93ED003A7C41 /* CADecoder.h */, 259 | F49DF8081BAF93ED003A7C41 /* CADecoder.m */, 260 | ); 261 | path = Decode; 262 | sourceTree = ""; 263 | }; 264 | F49DF7F81BAF8F25003A7C41 /* Utility */ = { 265 | isa = PBXGroup; 266 | children = ( 267 | F49DF8011BAF93DB003A7C41 /* CircularBuffer.h */, 268 | F49DF8021BAF93DB003A7C41 /* CircularBuffer.m */, 269 | ); 270 | path = Utility; 271 | sourceTree = ""; 272 | }; 273 | F49DF7F91BAF8F35003A7C41 /* Encode */ = { 274 | isa = PBXGroup; 275 | children = ( 276 | F4727BA61D478EA200B15C13 /* MP3Encoder.h */, 277 | F4727BA51D478EA200B15C13 /* MP3Encoder.m */, 278 | F47CAFE51D9154BA00CFAB41 /* MP3EncoderDelegateProtocol.h */, 279 | F45155541D5F6E9200B6FDEF /* EncoderTask.h */, 280 | F45155551D5F6E9200B6FDEF /* EncoderTask.m */, 281 | ); 282 | path = Encode; 283 | sourceTree = ""; 284 | }; 285 | F4D917DD222D570F00D4A594 /* Other */ = { 286 | isa = PBXGroup; 287 | children = ( 288 | 4A24129723A4E7D600B43215 /* CACDebug.h */, 289 | 4A24129823A4E7D600B43215 /* CACDebug.m */, 290 | F4D917DF222D641500D4A594 /* CACError.h */, 291 | F4D917E0222D641500D4A594 /* CACError.m */, 292 | ); 293 | name = Other; 294 | sourceTree = ""; 295 | }; 296 | F4ED6ABD1D8F819B001DB076 /* Frameworks */ = { 297 | isa = PBXGroup; 298 | children = ( 299 | 4A874B6E24AA90B0001E648A /* TagLib.framework */, 300 | 4AC69CD823A54BF3008E0532 /* AudioFileTagger.framework */, 301 | ); 302 | name = Frameworks; 303 | sourceTree = ""; 304 | }; 305 | /* End PBXGroup section */ 306 | 307 | /* Begin PBXHeadersBuildPhase section */ 308 | F49DF7D51BAF8D63003A7C41 /* Headers */ = { 309 | isa = PBXHeadersBuildPhase; 310 | buildActionMask = 2147483647; 311 | files = ( 312 | F47CAFE71D9154BA00CFAB41 /* MP3EncoderDelegateProtocol.h in Headers */, 313 | F45155561D5F6E9200B6FDEF /* EncoderTask.h in Headers */, 314 | F49DF7DC1BAF8D63003A7C41 /* CoreAudioConverter.h in Headers */, 315 | 4A24129923A4E7D600B43215 /* CACDebug.h in Headers */, 316 | F49DF8091BAF93ED003A7C41 /* CADecoder.h in Headers */, 317 | F49DF8051BAF93DB003A7C41 /* CircularBuffer.h in Headers */, 318 | F4727BA81D478EA200B15C13 /* MP3Encoder.h in Headers */, 319 | F4D917E1222D641500D4A594 /* CACError.h in Headers */, 320 | F44BC1311D7986B4008D9CF1 /* NSFileManager+FileAccess.h in Headers */, 321 | F474F08E1D55154E007BF84D /* NSError+Exceptions.h in Headers */, 322 | ); 323 | runOnlyForDeploymentPostprocessing = 0; 324 | }; 325 | /* End PBXHeadersBuildPhase section */ 326 | 327 | /* Begin PBXNativeTarget section */ 328 | F478E1AA1C7D2E8D00670966 /* CoreAudioConverterTests */ = { 329 | isa = PBXNativeTarget; 330 | buildConfigurationList = F478E1B31C7D2E8D00670966 /* Build configuration list for PBXNativeTarget "CoreAudioConverterTests" */; 331 | buildPhases = ( 332 | F478E1A71C7D2E8D00670966 /* Sources */, 333 | F478E1A81C7D2E8D00670966 /* Frameworks */, 334 | 4A874B6B24AA8F3B001E648A /* Copy Dependent Frameworks */, 335 | F478E1A91C7D2E8D00670966 /* Resources */, 336 | ); 337 | buildRules = ( 338 | ); 339 | dependencies = ( 340 | F408FEE71D52704000440412 /* PBXTargetDependency */, 341 | ); 342 | name = CoreAudioConverterTests; 343 | productName = CoreAudioConverterTests; 344 | productReference = F478E1AB1C7D2E8D00670966 /* CoreAudioConverterTests.xctest */; 345 | productType = "com.apple.product-type.bundle.unit-test"; 346 | }; 347 | F49DF7D71BAF8D63003A7C41 /* CoreAudioConverter macOS */ = { 348 | isa = PBXNativeTarget; 349 | buildConfigurationList = F49DF7E01BAF8D63003A7C41 /* Build configuration list for PBXNativeTarget "CoreAudioConverter macOS" */; 350 | buildPhases = ( 351 | 4A24129B23A4F6E200B43215 /* Update Localization */, 352 | F49DF7D31BAF8D63003A7C41 /* Sources */, 353 | F49DF7D41BAF8D63003A7C41 /* Frameworks */, 354 | F49DF7D51BAF8D63003A7C41 /* Headers */, 355 | F4ED6A981D8F7E61001DB076 /* Increment Build Number */, 356 | ); 357 | buildRules = ( 358 | ); 359 | dependencies = ( 360 | ); 361 | name = "CoreAudioConverter macOS"; 362 | packageProductDependencies = ( 363 | 4AD7494F2ADE0C81006F48EB /* lame */, 364 | ); 365 | productName = CoreAudioConverter; 366 | productReference = F49DF7D81BAF8D63003A7C41 /* CoreAudioConverter.framework */; 367 | productType = "com.apple.product-type.framework"; 368 | }; 369 | /* End PBXNativeTarget section */ 370 | 371 | /* Begin PBXProject section */ 372 | F49DF7CF1BAF8D63003A7C41 /* Project object */ = { 373 | isa = PBXProject; 374 | attributes = { 375 | BuildIndependentTargetsInParallel = YES; 376 | LastUpgradeCheck = 1500; 377 | ORGANIZATIONNAME = "Simon Gaus"; 378 | TargetAttributes = { 379 | F478E1AA1C7D2E8D00670966 = { 380 | CreatedOnToolsVersion = 7.2; 381 | }; 382 | F47CAFD71D91454400CFAB41 = { 383 | CreatedOnToolsVersion = 8.0; 384 | DevelopmentTeam = N67G6688LK; 385 | ProvisioningStyle = Automatic; 386 | }; 387 | F49DF7D71BAF8D63003A7C41 = { 388 | CreatedOnToolsVersion = 7.0; 389 | ProvisioningStyle = Automatic; 390 | }; 391 | }; 392 | }; 393 | buildConfigurationList = F49DF7D21BAF8D63003A7C41 /* Build configuration list for PBXProject "CoreAudioConverter" */; 394 | compatibilityVersion = "Xcode 3.2"; 395 | developmentRegion = Germany; 396 | hasScannedForEncodings = 0; 397 | knownRegions = ( 398 | Germany, 399 | de, 400 | fr, 401 | en, 402 | Base, 403 | ); 404 | mainGroup = F49DF7CE1BAF8D63003A7C41; 405 | packageReferences = ( 406 | 4AD7494E2ADE0C81006F48EB /* XCRemoteSwiftPackageReference "swift-lame" */, 407 | ); 408 | productRefGroup = F49DF7D91BAF8D63003A7C41 /* Products */; 409 | projectDirPath = ""; 410 | projectRoot = ""; 411 | targets = ( 412 | F49DF7D71BAF8D63003A7C41 /* CoreAudioConverter macOS */, 413 | F478E1AA1C7D2E8D00670966 /* CoreAudioConverterTests */, 414 | F47CAFD71D91454400CFAB41 /* Documentation */, 415 | ); 416 | }; 417 | /* End PBXProject section */ 418 | 419 | /* Begin PBXResourcesBuildPhase section */ 420 | F478E1A91C7D2E8D00670966 /* Resources */ = { 421 | isa = PBXResourcesBuildPhase; 422 | buildActionMask = 2147483647; 423 | files = ( 424 | F4CE0C741D5C7D55009360C6 /* wrong_data.m4a in Resources */, 425 | F4CE0C751D5C7D55009360C6 /* wrong_filetype.wma in Resources */, 426 | F40F2A7B1CA99E0B00BDCF2B /* AIFF (Linear PCM 16 Bit Big Endian Ganzzahl mit Vorzeichen).aiff in Resources */, 427 | F40F2A761CA99E0B00BDCF2B /* test-cover.jpg in Resources */, 428 | F4CE0C711D5C7AB7009360C6 /* WAV Microsoft (Signed 16 bit PCM).wav in Resources */, 429 | F40F2A7F1CA99E0B00BDCF2B /* AAC 44.100 Hz Stereo 80 kbits:s (HE).m4a in Resources */, 430 | F40F2A7C1CA99E0B00BDCF2B /* AIFF (Linear PCM 8 Bit Ganzzahl mit Vorzeichen).aiff in Resources */, 431 | F40F2A7E1CA99E0B00BDCF2B /* AAC 44.100 Hz Stereo 320 kbits:s.m4a in Resources */, 432 | F40F2A7A1CA99E0B00BDCF2B /* AIFF (Linear PCM 24 Bit Big Endian Ganzzahl mit Vorzeichen).aiff in Resources */, 433 | F40F2A771CA99E0B00BDCF2B /* Apple MPEG-4-Audio (AAC).m4a in Resources */, 434 | F40F2A791CA99E0B00BDCF2B /* AIFF 44100 Hz Stereo 16 Bit.aif in Resources */, 435 | F40F2A7D1CA99E0B00BDCF2B /* about.rtf in Resources */, 436 | F40F2A781CA99E0B00BDCF2B /* Apple Lossless.m4a in Resources */, 437 | ); 438 | runOnlyForDeploymentPostprocessing = 0; 439 | }; 440 | /* End PBXResourcesBuildPhase section */ 441 | 442 | /* Begin PBXShellScriptBuildPhase section */ 443 | 4A24129B23A4F6E200B43215 /* Update Localization */ = { 444 | isa = PBXShellScriptBuildPhase; 445 | alwaysOutOfDate = 1; 446 | buildActionMask = 2147483647; 447 | files = ( 448 | ); 449 | inputFileListPaths = ( 450 | ); 451 | inputPaths = ( 452 | ); 453 | name = "Update Localization"; 454 | outputFileListPaths = ( 455 | ); 456 | outputPaths = ( 457 | ); 458 | runOnlyForDeploymentPostprocessing = 0; 459 | shellPath = /bin/sh; 460 | shellScript = "# Adds support for Apple Silicon brew directory\nexport PATH=\"$PATH:/opt/homebrew/bin\"\n\nif which bartycrouch > /dev/null; then\n bartycrouch update -x\n bartycrouch lint -x\nelse\n echo \"warning: BartyCrouch not installed, download it from https://github.com/Flinesoft/BartyCrouch\"\nfi\n"; 461 | }; 462 | F47CAFDF1D91454A00CFAB41 /* ShellScript */ = { 463 | isa = PBXShellScriptBuildPhase; 464 | buildActionMask = 2147483647; 465 | files = ( 466 | ); 467 | inputPaths = ( 468 | ); 469 | outputPaths = ( 470 | ); 471 | runOnlyForDeploymentPostprocessing = 0; 472 | shellPath = /bin/sh; 473 | shellScript = "#appledoc Xcode script\n# Start constants\ntarget=\"macosx\";\noutputPath=\"~/Documents/XCode/Mac Apps/Converter - Projekt/Documentation/CoreAudioConverter\";\n# End constants\n/usr/local/bin/appledoc \\\n--project-name \"${PROJECT_NAME}\" \\\n--output \"${outputPath}\" \\\n--docset-platform-family \"${target}\" \\\n--ignore \".m\" \\\n--index-desc \"~/Documents/XCode/Mac Apps/Converter - Projekt/CoreAudioConverter/README.md\" \\\n--logformat xcode \\\n\"${PROJECT_DIR}\""; 474 | }; 475 | F4ED6A981D8F7E61001DB076 /* Increment Build Number */ = { 476 | isa = PBXShellScriptBuildPhase; 477 | alwaysOutOfDate = 1; 478 | buildActionMask = 2147483647; 479 | files = ( 480 | ); 481 | inputPaths = ( 482 | ); 483 | name = "Increment Build Number"; 484 | outputPaths = ( 485 | ); 486 | runOnlyForDeploymentPostprocessing = 0; 487 | shellPath = /bin/bash; 488 | shellScript = "buildNumber=$(/usr/libexec/PlistBuddy -c \"Print CFBundleVersion\" \"$INFOPLIST_FILE\")\nbuildNumber=$(($buildNumber + 1))\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $buildNumber\" \"$INFOPLIST_FILE\"\n"; 489 | }; 490 | /* End PBXShellScriptBuildPhase section */ 491 | 492 | /* Begin PBXSourcesBuildPhase section */ 493 | F478E1A71C7D2E8D00670966 /* Sources */ = { 494 | isa = PBXSourcesBuildPhase; 495 | buildActionMask = 2147483647; 496 | files = ( 497 | F40F2A681CA99DE900BDCF2B /* MP3EncondingTests.m in Sources */, 498 | ); 499 | runOnlyForDeploymentPostprocessing = 0; 500 | }; 501 | F49DF7D31BAF8D63003A7C41 /* Sources */ = { 502 | isa = PBXSourcesBuildPhase; 503 | buildActionMask = 2147483647; 504 | files = ( 505 | F49DF80A1BAF93ED003A7C41 /* CADecoder.m in Sources */, 506 | F4D917E2222D641500D4A594 /* CACError.m in Sources */, 507 | F474F08F1D55154E007BF84D /* NSError+Exceptions.m in Sources */, 508 | F45155571D5F6E9200B6FDEF /* EncoderTask.m in Sources */, 509 | F49DF8061BAF93DB003A7C41 /* CircularBuffer.m in Sources */, 510 | F4727BA71D478EA200B15C13 /* MP3Encoder.m in Sources */, 511 | 4A24129A23A4E7D600B43215 /* CACDebug.m in Sources */, 512 | F44BC1321D7986B4008D9CF1 /* NSFileManager+FileAccess.m in Sources */, 513 | ); 514 | runOnlyForDeploymentPostprocessing = 0; 515 | }; 516 | /* End PBXSourcesBuildPhase section */ 517 | 518 | /* Begin PBXTargetDependency section */ 519 | F408FEE71D52704000440412 /* PBXTargetDependency */ = { 520 | isa = PBXTargetDependency; 521 | target = F49DF7D71BAF8D63003A7C41 /* CoreAudioConverter macOS */; 522 | targetProxy = F408FEE61D52704000440412 /* PBXContainerItemProxy */; 523 | }; 524 | /* End PBXTargetDependency section */ 525 | 526 | /* Begin PBXVariantGroup section */ 527 | F478E19B1C7D249C00670966 /* Localizable.strings */ = { 528 | isa = PBXVariantGroup; 529 | children = ( 530 | F478E19C1C7D249C00670966 /* fr */, 531 | F478E19F1C7D249C00670966 /* en */, 532 | F478E1A11C7D249C00670966 /* de */, 533 | F478E1A51C7D24B100670966 /* Base */, 534 | ); 535 | name = Localizable.strings; 536 | path = ..; 537 | sourceTree = ""; 538 | }; 539 | /* End PBXVariantGroup section */ 540 | 541 | /* Begin XCBuildConfiguration section */ 542 | F478E1B41C7D2E8D00670966 /* Debug */ = { 543 | isa = XCBuildConfiguration; 544 | buildSettings = { 545 | CODE_SIGN_IDENTITY = "-"; 546 | COMBINE_HIDPI_IMAGES = YES; 547 | DEAD_CODE_STRIPPING = YES; 548 | FRAMEWORK_SEARCH_PATHS = ( 549 | "$(inherited)", 550 | "$(PROJECT_DIR)/Carthage/Build/Mac", 551 | ); 552 | INFOPLIST_FILE = "Integration Test/Info.plist"; 553 | LD_RUNPATH_SEARCH_PATHS = ( 554 | "$(inherited)", 555 | "@executable_path/../Frameworks", 556 | "@loader_path/../Frameworks", 557 | ); 558 | LIBRARY_SEARCH_PATHS = ""; 559 | MACOSX_DEPLOYMENT_TARGET = 10.13; 560 | PRODUCT_BUNDLE_IDENTIFIER = de.simonsserver.CoreAudioConverterTests; 561 | PRODUCT_NAME = "$(TARGET_NAME)"; 562 | }; 563 | name = Debug; 564 | }; 565 | F478E1B51C7D2E8D00670966 /* Release */ = { 566 | isa = XCBuildConfiguration; 567 | buildSettings = { 568 | CODE_SIGN_IDENTITY = "-"; 569 | COMBINE_HIDPI_IMAGES = YES; 570 | DEAD_CODE_STRIPPING = YES; 571 | FRAMEWORK_SEARCH_PATHS = ( 572 | "$(inherited)", 573 | "$(PROJECT_DIR)/Carthage/Build/Mac", 574 | ); 575 | INFOPLIST_FILE = "Integration Test/Info.plist"; 576 | LD_RUNPATH_SEARCH_PATHS = ( 577 | "$(inherited)", 578 | "@executable_path/../Frameworks", 579 | "@loader_path/../Frameworks", 580 | ); 581 | LIBRARY_SEARCH_PATHS = ""; 582 | MACOSX_DEPLOYMENT_TARGET = 10.13; 583 | PRODUCT_BUNDLE_IDENTIFIER = de.simonsserver.CoreAudioConverterTests; 584 | PRODUCT_NAME = "$(TARGET_NAME)"; 585 | }; 586 | name = Release; 587 | }; 588 | F47CAFD81D91454400CFAB41 /* Debug */ = { 589 | isa = XCBuildConfiguration; 590 | buildSettings = { 591 | DEAD_CODE_STRIPPING = YES; 592 | DEVELOPMENT_TEAM = N67G6688LK; 593 | MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; 594 | PRODUCT_NAME = "$(TARGET_NAME)"; 595 | }; 596 | name = Debug; 597 | }; 598 | F47CAFD91D91454400CFAB41 /* Release */ = { 599 | isa = XCBuildConfiguration; 600 | buildSettings = { 601 | DEAD_CODE_STRIPPING = YES; 602 | DEVELOPMENT_TEAM = N67G6688LK; 603 | MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; 604 | PRODUCT_NAME = "$(TARGET_NAME)"; 605 | }; 606 | name = Release; 607 | }; 608 | F49DF7DE1BAF8D63003A7C41 /* Debug */ = { 609 | isa = XCBuildConfiguration; 610 | buildSettings = { 611 | ALWAYS_SEARCH_USER_PATHS = NO; 612 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 613 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 614 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 615 | CLANG_CXX_LIBRARY = "libc++"; 616 | CLANG_ENABLE_MODULES = YES; 617 | CLANG_ENABLE_OBJC_ARC = YES; 618 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 619 | CLANG_WARN_BOOL_CONVERSION = YES; 620 | CLANG_WARN_COMMA = YES; 621 | CLANG_WARN_CONSTANT_CONVERSION = YES; 622 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 623 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 624 | CLANG_WARN_EMPTY_BODY = YES; 625 | CLANG_WARN_ENUM_CONVERSION = YES; 626 | CLANG_WARN_INFINITE_RECURSION = YES; 627 | CLANG_WARN_INT_CONVERSION = YES; 628 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 629 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 630 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 631 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 632 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 633 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 634 | CLANG_WARN_STRICT_PROTOTYPES = YES; 635 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 636 | CLANG_WARN_UNREACHABLE_CODE = YES; 637 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 638 | COPY_PHASE_STRIP = NO; 639 | CURRENT_PROJECT_VERSION = 1; 640 | DEAD_CODE_STRIPPING = YES; 641 | DEBUG_INFORMATION_FORMAT = dwarf; 642 | DEFINES_MODULE = YES; 643 | ENABLE_MODULE_VERIFIER = YES; 644 | ENABLE_STRICT_OBJC_MSGSEND = YES; 645 | ENABLE_TESTABILITY = YES; 646 | GCC_C_LANGUAGE_STANDARD = gnu99; 647 | GCC_DYNAMIC_NO_PIC = NO; 648 | GCC_NO_COMMON_BLOCKS = YES; 649 | GCC_OPTIMIZATION_LEVEL = 0; 650 | GCC_PREPROCESSOR_DEFINITIONS = ( 651 | "DEBUG=1", 652 | "$(inherited)", 653 | ); 654 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 655 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 656 | GCC_WARN_UNDECLARED_SELECTOR = YES; 657 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 658 | GCC_WARN_UNUSED_FUNCTION = YES; 659 | GCC_WARN_UNUSED_VARIABLE = YES; 660 | MACOSX_DEPLOYMENT_TARGET = 10.13; 661 | MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; 662 | MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; 663 | MTL_ENABLE_DEBUG_INFO = YES; 664 | ONLY_ACTIVE_ARCH = YES; 665 | SDKROOT = macosx; 666 | VERSIONING_SYSTEM = "apple-generic"; 667 | VERSION_INFO_PREFIX = ""; 668 | }; 669 | name = Debug; 670 | }; 671 | F49DF7DF1BAF8D63003A7C41 /* Release */ = { 672 | isa = XCBuildConfiguration; 673 | buildSettings = { 674 | ALWAYS_SEARCH_USER_PATHS = NO; 675 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 676 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 677 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 678 | CLANG_CXX_LIBRARY = "libc++"; 679 | CLANG_ENABLE_MODULES = YES; 680 | CLANG_ENABLE_OBJC_ARC = YES; 681 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 682 | CLANG_WARN_BOOL_CONVERSION = YES; 683 | CLANG_WARN_COMMA = YES; 684 | CLANG_WARN_CONSTANT_CONVERSION = YES; 685 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 686 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 687 | CLANG_WARN_EMPTY_BODY = YES; 688 | CLANG_WARN_ENUM_CONVERSION = YES; 689 | CLANG_WARN_INFINITE_RECURSION = YES; 690 | CLANG_WARN_INT_CONVERSION = YES; 691 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 692 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 693 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 694 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 695 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 696 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 697 | CLANG_WARN_STRICT_PROTOTYPES = YES; 698 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 699 | CLANG_WARN_UNREACHABLE_CODE = YES; 700 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 701 | COPY_PHASE_STRIP = NO; 702 | CURRENT_PROJECT_VERSION = 1; 703 | DEAD_CODE_STRIPPING = YES; 704 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 705 | DEFINES_MODULE = YES; 706 | ENABLE_MODULE_VERIFIER = YES; 707 | ENABLE_NS_ASSERTIONS = NO; 708 | ENABLE_STRICT_OBJC_MSGSEND = YES; 709 | GCC_C_LANGUAGE_STANDARD = gnu99; 710 | GCC_NO_COMMON_BLOCKS = YES; 711 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 712 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 713 | GCC_WARN_UNDECLARED_SELECTOR = YES; 714 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 715 | GCC_WARN_UNUSED_FUNCTION = YES; 716 | GCC_WARN_UNUSED_VARIABLE = YES; 717 | MACOSX_DEPLOYMENT_TARGET = 10.13; 718 | MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; 719 | MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; 720 | MTL_ENABLE_DEBUG_INFO = NO; 721 | SDKROOT = macosx; 722 | VERSIONING_SYSTEM = "apple-generic"; 723 | VERSION_INFO_PREFIX = ""; 724 | }; 725 | name = Release; 726 | }; 727 | F49DF7E11BAF8D63003A7C41 /* Debug */ = { 728 | isa = XCBuildConfiguration; 729 | buildSettings = { 730 | CLANG_USE_OPTIMIZATION_PROFILE = YES; 731 | CODE_SIGN_IDENTITY = ""; 732 | CODE_SIGN_STYLE = Automatic; 733 | COMBINE_HIDPI_IMAGES = YES; 734 | DEAD_CODE_STRIPPING = YES; 735 | DEFINES_MODULE = YES; 736 | DEVELOPMENT_TEAM = ""; 737 | DYLIB_COMPATIBILITY_VERSION = 1; 738 | DYLIB_CURRENT_VERSION = 1; 739 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 740 | ENABLE_MODULE_VERIFIER = NO; 741 | FRAMEWORK_SEARCH_PATHS = ( 742 | "$(inherited)", 743 | "$(PROJECT_DIR)", 744 | "$(PROJECT_DIR)/Carthage/Build/Mac", 745 | ); 746 | FRAMEWORK_VERSION = A; 747 | GCC_INPUT_FILETYPE = sourcecode.c.objc; 748 | GCC_OPTIMIZATION_LEVEL = s; 749 | INFOPLIST_FILE = CoreAudioConverter/Info.plist; 750 | INSTALL_PATH = "@rpath"; 751 | LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)"; 752 | LD_RUNPATH_SEARCH_PATHS = ( 753 | "$(inherited)", 754 | "@executable_path/../Frameworks", 755 | "@loader_path/Frameworks", 756 | ); 757 | LIBRARY_SEARCH_PATHS = ( 758 | "$(inherited)", 759 | "$(PROJECT_DIR)/CoreAudioConverter", 760 | ); 761 | LLVM_LTO = YES; 762 | MACOSX_DEPLOYMENT_TARGET = 10.13; 763 | MODULEMAP_FILE = ""; 764 | MODULEMAP_PRIVATE_FILE = ""; 765 | MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; 766 | MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; 767 | OTHER_CFLAGS = ""; 768 | OTHER_MODULE_VERIFIER_FLAGS = "$(OTHER_CLANG_MODULES_VERIFIER_FLAGS)"; 769 | PRODUCT_BUNDLE_IDENTIFIER = de.simonsserver.CoreAudioConverter; 770 | PRODUCT_NAME = CoreAudioConverter; 771 | PROVISIONING_PROFILE_SPECIFIER = ""; 772 | SKIP_INSTALL = YES; 773 | USER_HEADER_SEARCH_PATHS = ""; 774 | WARNING_CFLAGS = ""; 775 | }; 776 | name = Debug; 777 | }; 778 | F49DF7E21BAF8D63003A7C41 /* Release */ = { 779 | isa = XCBuildConfiguration; 780 | buildSettings = { 781 | CLANG_USE_OPTIMIZATION_PROFILE = YES; 782 | CODE_SIGN_IDENTITY = ""; 783 | CODE_SIGN_STYLE = Automatic; 784 | COMBINE_HIDPI_IMAGES = YES; 785 | DEAD_CODE_STRIPPING = YES; 786 | DEFINES_MODULE = YES; 787 | DEVELOPMENT_TEAM = ""; 788 | DYLIB_COMPATIBILITY_VERSION = 1; 789 | DYLIB_CURRENT_VERSION = 1; 790 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 791 | ENABLE_MODULE_VERIFIER = NO; 792 | FRAMEWORK_SEARCH_PATHS = ( 793 | "$(inherited)", 794 | "$(PROJECT_DIR)", 795 | "$(PROJECT_DIR)/Carthage/Build/Mac", 796 | ); 797 | FRAMEWORK_VERSION = A; 798 | GCC_INPUT_FILETYPE = sourcecode.c.objc; 799 | GCC_OPTIMIZATION_LEVEL = s; 800 | INFOPLIST_FILE = CoreAudioConverter/Info.plist; 801 | INSTALL_PATH = "@rpath"; 802 | LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)"; 803 | LD_RUNPATH_SEARCH_PATHS = ( 804 | "$(inherited)", 805 | "@executable_path/../Frameworks", 806 | "@loader_path/Frameworks", 807 | ); 808 | LIBRARY_SEARCH_PATHS = ( 809 | "$(inherited)", 810 | "$(PROJECT_DIR)/CoreAudioConverter", 811 | ); 812 | LLVM_LTO = YES; 813 | MACOSX_DEPLOYMENT_TARGET = 10.13; 814 | MODULEMAP_FILE = ""; 815 | MODULEMAP_PRIVATE_FILE = ""; 816 | MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; 817 | MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; 818 | OTHER_CFLAGS = ""; 819 | OTHER_MODULE_VERIFIER_FLAGS = "$(OTHER_CLANG_MODULES_VERIFIER_FLAGS)"; 820 | PRODUCT_BUNDLE_IDENTIFIER = de.simonsserver.CoreAudioConverter; 821 | PRODUCT_NAME = CoreAudioConverter; 822 | PROVISIONING_PROFILE_SPECIFIER = ""; 823 | SKIP_INSTALL = YES; 824 | USER_HEADER_SEARCH_PATHS = ""; 825 | WARNING_CFLAGS = ""; 826 | }; 827 | name = Release; 828 | }; 829 | /* End XCBuildConfiguration section */ 830 | 831 | /* Begin XCConfigurationList section */ 832 | F478E1B31C7D2E8D00670966 /* Build configuration list for PBXNativeTarget "CoreAudioConverterTests" */ = { 833 | isa = XCConfigurationList; 834 | buildConfigurations = ( 835 | F478E1B41C7D2E8D00670966 /* Debug */, 836 | F478E1B51C7D2E8D00670966 /* Release */, 837 | ); 838 | defaultConfigurationIsVisible = 0; 839 | defaultConfigurationName = Release; 840 | }; 841 | F47CAFDE1D91454400CFAB41 /* Build configuration list for PBXAggregateTarget "Documentation" */ = { 842 | isa = XCConfigurationList; 843 | buildConfigurations = ( 844 | F47CAFD81D91454400CFAB41 /* Debug */, 845 | F47CAFD91D91454400CFAB41 /* Release */, 846 | ); 847 | defaultConfigurationIsVisible = 0; 848 | defaultConfigurationName = Release; 849 | }; 850 | F49DF7D21BAF8D63003A7C41 /* Build configuration list for PBXProject "CoreAudioConverter" */ = { 851 | isa = XCConfigurationList; 852 | buildConfigurations = ( 853 | F49DF7DE1BAF8D63003A7C41 /* Debug */, 854 | F49DF7DF1BAF8D63003A7C41 /* Release */, 855 | ); 856 | defaultConfigurationIsVisible = 0; 857 | defaultConfigurationName = Release; 858 | }; 859 | F49DF7E01BAF8D63003A7C41 /* Build configuration list for PBXNativeTarget "CoreAudioConverter macOS" */ = { 860 | isa = XCConfigurationList; 861 | buildConfigurations = ( 862 | F49DF7E11BAF8D63003A7C41 /* Debug */, 863 | F49DF7E21BAF8D63003A7C41 /* Release */, 864 | ); 865 | defaultConfigurationIsVisible = 0; 866 | defaultConfigurationName = Release; 867 | }; 868 | /* End XCConfigurationList section */ 869 | 870 | /* Begin XCRemoteSwiftPackageReference section */ 871 | 4AD7494E2ADE0C81006F48EB /* XCRemoteSwiftPackageReference "swift-lame" */ = { 872 | isa = XCRemoteSwiftPackageReference; 873 | repositoryURL = "https://github.com/Phisto/swift-lame.git"; 874 | requirement = { 875 | kind = upToNextMajorVersion; 876 | minimumVersion = 3.100.0; 877 | }; 878 | }; 879 | /* End XCRemoteSwiftPackageReference section */ 880 | 881 | /* Begin XCSwiftPackageProductDependency section */ 882 | 4AD7494F2ADE0C81006F48EB /* lame */ = { 883 | isa = XCSwiftPackageProductDependency; 884 | package = 4AD7494E2ADE0C81006F48EB /* XCRemoteSwiftPackageReference "swift-lame" */; 885 | productName = lame; 886 | }; 887 | /* End XCSwiftPackageProductDependency section */ 888 | }; 889 | rootObject = F49DF7CF1BAF8D63003A7C41 /* Project object */; 890 | } 891 | -------------------------------------------------------------------------------- /CoreAudioConverter.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CoreAudioConverter.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /CoreAudioConverter.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "pins" : [ 3 | { 4 | "identity" : "swift-lame", 5 | "kind" : "remoteSourceControl", 6 | "location" : "https://github.com/Phisto/swift-lame.git", 7 | "state" : { 8 | "revision" : "d85ee80128d7cc36796c984463cfd75b1d38587d", 9 | "version" : "3.100.0" 10 | } 11 | } 12 | ], 13 | "version" : 2 14 | } 15 | -------------------------------------------------------------------------------- /CoreAudioConverter.xcodeproj/xcshareddata/xcbaselines/F478E1AA1C7D2E8D00670966.xcbaseline/F6BD7D74-226C-46E5-9E25-997D3E7DF5FD.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | classNames 6 | 7 | MP3EncondingTests 8 | 9 | testEncodingPerformance 10 | 11 | com.apple.XCTPerformanceMetric_WallClockTime 12 | 13 | baselineAverage 14 | 1.208 15 | baselineIntegrationDisplayName 16 | Local Baseline 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /CoreAudioConverter.xcodeproj/xcshareddata/xcbaselines/F478E1AA1C7D2E8D00670966.xcbaseline/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | runDestinationsByUUID 6 | 7 | F6BD7D74-226C-46E5-9E25-997D3E7DF5FD 8 | 9 | localComputer 10 | 11 | busSpeedInMHz 12 | 100 13 | cpuCount 14 | 1 15 | cpuKind 16 | Intel Core i7 17 | cpuSpeedInMHz 18 | 2300 19 | logicalCPUCoresPerPackage 20 | 8 21 | modelCode 22 | MacBookPro9,1 23 | physicalCPUCoresPerPackage 24 | 4 25 | platformIdentifier 26 | com.apple.platform.macosx 27 | 28 | targetArchitecture 29 | x86_64 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /CoreAudioConverter.xcodeproj/xcshareddata/xcschemes/CoreAudioConverter macOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 54 | 60 | 61 | 67 | 68 | 69 | 70 | 72 | 73 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /CoreAudioConverter.xcodeproj/xcuserdata/Simon.xcuserdatad/xcschemes/CoreAudioConverter.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 34 | 40 | 41 | 42 | 43 | 44 | 50 | 51 | 52 | 53 | 54 | 55 | 65 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 84 | 90 | 91 | 92 | 93 | 95 | 96 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /CoreAudioConverter.xcodeproj/xcuserdata/Simon.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CoreAudioConverter.xcscheme 8 | 9 | orderHint 10 | 6 11 | 12 | CoreAudioConverterTests.xcscheme 13 | 14 | orderHint 15 | 5 16 | 17 | Documentation.xcscheme 18 | 19 | orderHint 20 | 7 21 | 22 | 23 | SuppressBuildableAutocreation 24 | 25 | F44E54B61D5F31B000B41FCE 26 | 27 | primary 28 | 29 | 30 | F478E18A1C7CF8C900670966 31 | 32 | primary 33 | 34 | 35 | F478E1AA1C7D2E8D00670966 36 | 37 | primary 38 | 39 | 40 | F47CAFD71D91454400CFAB41 41 | 42 | primary 43 | 44 | 45 | F49DF7D71BAF8D63003A7C41 46 | 47 | primary 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /CoreAudioConverter/Base.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* Error description - Returned if an unknown error occurred inside of LAME. */ 2 | "An error occurred inside of LAME, while encoding the file: '%@'." = "An error occurred inside of LAME, while encoding the file: '%@'."; 3 | 4 | /* Error description - Returned if an unknown error occurred. */ 5 | "An unknown error occurred." = "An unknown error occurred."; 6 | 7 | /* Error description - Returned if an I/O error occurred. */ 8 | "Beim lesen/schreiben ist ein Fehler aufgetreten." = "An error occurred while reading/writing."; 9 | 10 | /* Error description - Returned if the decoder for the given file could not be create. */ 11 | "Couldn't create decoder for file: '%@'." = "Couldn't create decoder for file: '%@'."; 12 | 13 | /* Error description - Returned if the file type of the input file couldent be detected. */ 14 | "Couldn't detect type for file: '%@', the file may be corrupted." = "Couldn't detect type for file: '%@', the file may be corrupted."; 15 | 16 | /* Error description - Returned if the input file couldent be opened. */ 17 | "Couldn't open the file '%@', the file may be corrupted." = "Couldn't open the file '%@', the file may be corrupted."; 18 | 19 | /* Error description - Returned if a folder was expected and a file was passed. */ 20 | "Das angegebene Objekt ist kein Ordner." = "The specified object is not a folder."; 21 | 22 | /* Error description - Returned if the file system is busy and cannot be removed. */ 23 | "Das Laufwerk ist beschäftigt und kann nicht entfernt werden." = "The drive is busy and cannot be removed."; 24 | 25 | /* Error description - Returned if the volume can't be ejected because it is used by the VM. */ 26 | "Das Laufwerk kann nicht ausgeworfen werden, weil es von der VM benutzt wird." = "The drive cannot be ejected because it is being used by the VM."; 27 | 28 | /* Error description - Returned if there is no such volume. */ 29 | "Das Laufwerk konnte nicht gefunden werden." = "The drive could not be found."; 30 | 31 | /* Error description - Returned if the file/volume is beeing used by another process. */ 32 | "Das Volumen kann nicht ausgeworfen werden, weil es von einem anderen Prozess verwendet wird." = "The volume cannot be ejected because it is being used by another process."; 33 | 34 | /* Error description - Returned if a bad file name was passed to the routine. */ 35 | "Der Dateiname ist nicht zulässig." = "The file name is not allowed."; 36 | 37 | /* Error description - Returned if the selector is not recognized by the filesystem. */ 38 | "Die Aktion wird von dem Dateisystem nicht unterstützt." = "The action is not supported by the file system."; 39 | 40 | /* Error description - Returned if the file or volume is too big for the system. */ 41 | "Die Datei oder Partition ist zu groß." = "The file or partition is too large."; 42 | 43 | /* Error description - Returned if the attempted operation is not supported by the filesystem. */ 44 | "Die Operation wird von dem Dateisystem nicht unterstützt." = "The operation is not supported by the file system."; 45 | 46 | /* Error description - Returned if the operation was canceled by the user. */ 47 | "Die Operation wurde vom Nutzer abgebrochen." = "The operation was canceled by the user."; 48 | 49 | /* Error description - Returned if there occurred an unknown Core Foundation error. */ 50 | "Es ist ein unbekannter Fehler im Core Foundation Framework aufgetreten." = "An unknown error has occurred in the Core Foundation Framework."; 51 | 52 | /* Error description - Returned if there is no space on the disk. */ 53 | "Es ist kein Platz mehr auf dem Laufwerk." = "There is no more space on the drive."; 54 | 55 | /* Error description - Returned if there is not enough disk space to perform the requested operation. */ 56 | "Es ist nicht genügend Speicherplatz vorhanden um die Operation auszuführen." = "There is not enough space to perform the operation."; 57 | 58 | /* Error description - Returned if the file format is not supported. */ 59 | "File format not supported for file: '%@'" = "File format not supported for file: '%@'"; 60 | 61 | /* Error description - Returned if a file has more than 2 channels. */ 62 | "LAME only supports one or two channel input. %@." = "LAME only supports one or two channel input. %@."; 63 | 64 | /* Error description - Returned if a file has an unsupported sample size. */ 65 | "LAME only supports sample sizes of 8, 16, 24 and 32. %@." = "LAME only supports sample sizes of 8, 16, 24 and 32. %@."; 66 | 67 | /* Error description - Returned if LAME was unable to flush the buffer for a file. */ 68 | "LAME was unable to flush the buffers for file: '%@'." = "LAME was unable to flush the buffers for file: '%@'."; 69 | 70 | /* Error description - Returned if the process is not allowed to access the requested file. */ 71 | "The process is not allowed to access the requested file at path '%@'." = "The process is not allowed to access the requested file at path '%@'."; 72 | 73 | /* Error description - Returned if there is not enough disc space to encode the file */ 74 | "There is not enough disc space to encode the file at path '%@'." = "There is not enough disc space to encode the file at path '%@'."; 75 | 76 | /* Error description - Returned if the output file could not be closed. */ 77 | "Unable to allocate memory." = "Unable to allocate memory."; 78 | 79 | /* Error description - Returned if the output file could not be closed. */ 80 | "Unable to close the output file: '%@'." = "Unable to close the output file: '%@'."; 81 | 82 | /* Error description - Returned if the lame settings couldent be set. */ 83 | "Unable to initialize the LAME settings. Failed with code: %@" = "Unable to initialize the LAME settings. Failed with code: %@"; 84 | 85 | /* Error description - Returned if the output file could not be opened. */ 86 | "Unable to open the output file: '%@'." = "Unable to open the output file: '%@'."; 87 | -------------------------------------------------------------------------------- /CoreAudioConverter/CACDebug.m: -------------------------------------------------------------------------------- 1 | /* 2 | * CACDebug.m 3 | * CoreAudioConverter 4 | * 5 | * Copyright © 2015-2020 Simon Gaus 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the Lesser General Public License (LGPL) as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | * 20 | */ 21 | 22 | #import "CACDebug.h" 23 | 24 | #pragma mark - IMPLEMENTATION 25 | 26 | void CACLog(CACDebugLevel debugLevel, NSString *format, ...) { 27 | 28 | #if DEBUG 29 | 30 | va_list argp; 31 | va_start(argp, format); 32 | __unused NSString *log = [[NSString alloc] initWithFormat:format arguments:argp]; 33 | va_end(argp); 34 | 35 | #pragma GCC diagnostic push 36 | #pragma GCC diagnostic ignored "-Wunreachable-code" 37 | 38 | if (debugLevel == CACDebugLevelFatal) { 39 | if (DEBUG_LEVEL >= CACDebugLevelFatal) { 40 | NSLog(@"%@", log); 41 | } 42 | } 43 | else if (debugLevel == CACDebugLevelError) { 44 | if (DEBUG_LEVEL >= CACDebugLevelError) { 45 | NSLog(@"%@", log); 46 | } 47 | } 48 | else if (debugLevel == CACDebugLevelInfo) { 49 | if (DEBUG_LEVEL >= CACDebugLevelInfo) { 50 | NSLog(@"%@", log); 51 | } 52 | } 53 | else if (debugLevel == CACDebugLevelTrace) { 54 | if (DEBUG_LEVEL >= CACDebugLevelTrace) { 55 | NSLog(@"%@", log); 56 | } 57 | } 58 | 59 | #pragma GCC diagnostic pop 60 | 61 | #endif 62 | } 63 | 64 | #pragma mark - 65 | -------------------------------------------------------------------------------- /CoreAudioConverter/CACError.h: -------------------------------------------------------------------------------- 1 | // 2 | // CACError.h 3 | // CoreAudioConverter 4 | // 5 | // Created by Simon Gaus on 04.03.19. 6 | // Copyright © 2019 Simon Gaus. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | #pragma mark - Error domain 14 | ///-------------------------------------- 15 | /// @name Error domain 16 | ///-------------------------------------- 17 | 18 | 19 | 20 | /// The error domain for the Core Audio Converter framework. 21 | FOUNDATION_EXPORT NSString * const CoreAudioConverterErrorDomain; 22 | 23 | 24 | 25 | #pragma mark - Error codes 26 | ///------------------------------------- 27 | /// @name Error codes 28 | ///------------------------------------- 29 | 30 | /** 31 | 32 | These constants define the application specific error codes. 33 | 34 | */ 35 | typedef NS_ENUM(NSUInteger, CACErrorCode) { 36 | 37 | /// The file is not accessible by this process. 38 | CACFilePermissionDenied = 1888, 39 | /// There is not enough disc space to continue 40 | CACNotEnoughDiscSpace = 1889, 41 | /// LAME only supports one or two channel input. 42 | CACTooMayChannels = 1890, 43 | /// LAME could not be initialized. 44 | CACLameSettingsInitFailed = 1891, 45 | /// The output file couldent be accessed. 46 | CACOutputAccessFailed = 1892, 47 | /// The output file couldent be closed. 48 | CACOutputClosingFailed = 1893, 49 | /// Couldent allocate memory. 50 | CACMemoryAllocationFailed = 1894, 51 | /// LAME only supports certain sample sizes. 52 | CACUnsupportedSampleSize = 1895, 53 | /// An error occurred inside of LAME, reason unknown. 54 | CACUnknownLAMEError = 1896, 55 | /// LAME was unable to flush the buffer. 56 | CACLameBufferFlushFailed = 1897, 57 | /// The input file couldent be opened. 58 | CACFailedToOpenInputFile = 1898, 59 | /// The file type of the input file couldent be detected. 60 | CACUnknownFileType = 1899, 61 | /// Could not create decoder for the given file. 62 | CACFailedToCreateDecoder = 1900, 63 | /// The file format is not supported. 64 | CACFileFormatNotSupported = 1901 65 | }; 66 | 67 | 68 | 69 | #pragma mark - Creating errors 70 | ///------------------------------------------- 71 | /// @name Creating errors 72 | ///------------------------------------------- 73 | 74 | /** 75 | 76 | @brief This funktion will create and return a configured error object. If there is no CoreAudioConverter specific error for the given code, the funktion will try to find a matching system error. 77 | 78 | @param code The error code. 79 | 80 | @param userInfo Miscellaneous string to provide more detailed error messages. Currently unused. 81 | 82 | @return The newly created error object. 83 | 84 | */ 85 | 86 | __attribute__((annotate("returns_localized_nsstring"))) 87 | NSError * cac_error( CACErrorCode code, NSString * _Nullable __unused userInfo ); 88 | 89 | /** 90 | 91 | This funktion will create and return a configured error object. 92 | 93 | @param code The OSStatus/SCError error code. 94 | 95 | @return The newly created error object. 96 | 97 | */ 98 | __attribute__((annotate("returns_localized_nsstring"))) 99 | NSError * cac_OSStatusError( OSStatus code ); 100 | 101 | 102 | 103 | NS_ASSUME_NONNULL_END 104 | -------------------------------------------------------------------------------- /CoreAudioConverter/CACError.m: -------------------------------------------------------------------------------- 1 | // 2 | // CACError.m 3 | // CoreAudioConverter 4 | // 5 | // Created by Simon Gaus on 04.03.19. 6 | // Copyright © 2019 Simon Gaus. All rights reserved. 7 | // 8 | 9 | #import "CACError.h" 10 | 11 | #pragma mark - Constants 12 | 13 | static NSString * const kCoreAudioConverterIdentifier = @"de.simonsserver.CoreAudioConverter"; 14 | 15 | #pragma mark - HUSync Error Domain 16 | 17 | NSString * const CoreAudioConverterErrorDomain = @"de.simonsserver.CoreAudioConverter.error"; 18 | 19 | #pragma mark - Funktion Prototypes 20 | 21 | NSString * cac_errorDescription( CACErrorCode code, NSString * _Nullable userinfo); 22 | NSString * cac_systemErrorDescription(NSInteger code ); 23 | 24 | #pragma mark - Convenient Error Creation 25 | 26 | NSError * cac_error( CACErrorCode code, NSString * _Nullable __unused userInfo ) { 27 | 28 | NSString *errorDomain = CoreAudioConverterErrorDomain; 29 | NSString *description = cac_errorDescription(code, userInfo); 30 | 31 | // try to find a matching system error 32 | if (!description) { 33 | 34 | errorDomain = NSCocoaErrorDomain; 35 | description = cac_systemErrorDescription(code); 36 | } 37 | 38 | NSError *error = [NSError errorWithDomain:errorDomain 39 | code:code 40 | userInfo:@{ NSLocalizedDescriptionKey : description }]; 41 | return error; 42 | } 43 | 44 | inline NSString * cac_errorDescription( CACErrorCode code , NSString * _Nullable userinfo) { 45 | 46 | NSString *descr = nil; 47 | 48 | switch (code) { 49 | 50 | case CACFilePermissionDenied: { 51 | NSString *locFormatString = NSLocalizedStringFromTableInBundle(@"The process is not allowed to access the requested file at path '%@'.", 52 | @"Localizable", 53 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 54 | @"Error description - Returned if the process is not allowed to access the requested file."); 55 | descr = [NSString stringWithFormat:locFormatString, userinfo]; 56 | break; 57 | } 58 | 59 | case CACNotEnoughDiscSpace: { 60 | NSString *locFormatString = NSLocalizedStringFromTableInBundle(@"There is not enough disc space to encode the file at path '%@'.", 61 | @"Localizable", 62 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 63 | @"Error description - Returned if there is not enough disc space to encode the file"); 64 | descr = [NSString stringWithFormat:locFormatString, userinfo]; 65 | break; 66 | } 67 | 68 | case CACTooMayChannels: { 69 | NSString *locFormatString = NSLocalizedStringFromTableInBundle(@"LAME only supports one or two channel input. %@.", 70 | @"Localizable", 71 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 72 | @"Error description - Returned if a file has more than 2 channels."); 73 | descr = [NSString stringWithFormat:locFormatString, userinfo]; 74 | break; 75 | } 76 | 77 | 78 | case CACLameSettingsInitFailed: { 79 | NSString *locFormatString = NSLocalizedStringFromTableInBundle(@"Unable to initialize the LAME settings. Failed with code: %@", 80 | @"Localizable", 81 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 82 | @"Error description - Returned if the lame settings couldent be set."); 83 | descr = [NSString stringWithFormat:locFormatString, userinfo]; 84 | break; 85 | } 86 | 87 | case CACOutputAccessFailed: { 88 | NSString *locFormatString = NSLocalizedStringFromTableInBundle(@"Unable to open the output file: '%@'.", 89 | @"Localizable", 90 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 91 | @"Error description - Returned if the output file could not be opened."); 92 | descr = [NSString stringWithFormat:locFormatString, userinfo]; 93 | break; 94 | } 95 | 96 | case CACOutputClosingFailed: { 97 | NSString *locFormatString = NSLocalizedStringFromTableInBundle(@"Unable to close the output file: '%@'.", 98 | @"Localizable", 99 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 100 | @"Error description - Returned if the output file could not be closed."); 101 | descr = [NSString stringWithFormat:locFormatString, userinfo]; 102 | break; 103 | } 104 | 105 | case CACMemoryAllocationFailed: { 106 | descr = NSLocalizedStringFromTableInBundle(@"Unable to allocate memory.", 107 | @"Localizable", 108 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 109 | @"Error description - Returned if the output file could not be closed."); 110 | break; 111 | } 112 | 113 | case CACUnsupportedSampleSize: { 114 | NSString *locFormatString = NSLocalizedStringFromTableInBundle(@"LAME only supports sample sizes of 8, 16, 24 and 32. %@.", 115 | @"Localizable", 116 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 117 | @"Error description - Returned if a file has an unsupported sample size."); 118 | descr = [NSString stringWithFormat:locFormatString, userinfo]; 119 | break; 120 | } 121 | 122 | case CACUnknownLAMEError: { 123 | NSString *locFormatString = NSLocalizedStringFromTableInBundle(@"An error occurred inside of LAME, while encoding the file: '%@'.", 124 | @"Localizable", 125 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 126 | @"Error description - Returned if an unknown error occurred inside of LAME."); 127 | descr = [NSString stringWithFormat:locFormatString, userinfo]; 128 | break; 129 | } 130 | 131 | case CACLameBufferFlushFailed: { 132 | NSString *locFormatString = NSLocalizedStringFromTableInBundle(@"LAME was unable to flush the buffers for file: '%@'.", 133 | @"Localizable", 134 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 135 | @"Error description - Returned if LAME was unable to flush the buffer for a file."); 136 | descr = [NSString stringWithFormat:locFormatString, userinfo]; 137 | break; 138 | } 139 | 140 | case CACFailedToOpenInputFile: { 141 | NSString *locFormatString = NSLocalizedStringFromTableInBundle(@"Couldn't open the file '%@', the file may be corrupted.", 142 | @"Localizable", 143 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 144 | @"Error description - Returned if the input file couldent be opened."); 145 | descr = [NSString stringWithFormat:locFormatString, userinfo]; 146 | break; 147 | } 148 | 149 | case CACUnknownFileType: { 150 | NSString *locFormatString = NSLocalizedStringFromTableInBundle(@"Couldn't detect type for file: '%@', the file may be corrupted.", 151 | @"Localizable", 152 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 153 | @"Error description - Returned if the file type of the input file couldent be detected."); 154 | descr = [NSString stringWithFormat:locFormatString, userinfo]; 155 | break; 156 | } 157 | 158 | case CACFailedToCreateDecoder: { 159 | NSString *locFormatString = NSLocalizedStringFromTableInBundle(@"Couldn't create decoder for file: '%@'.", 160 | @"Localizable", 161 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 162 | @"Error description - Returned if the decoder for the given file could not be create."); 163 | descr = [NSString stringWithFormat:locFormatString, userinfo]; 164 | break; 165 | } 166 | 167 | case CACFileFormatNotSupported: { 168 | NSString *locFormatString = NSLocalizedStringFromTableInBundle(@"File format not supported for file: '%@'", 169 | @"Localizable", 170 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 171 | @"Error description - Returned if the file format is not supported."); 172 | descr = [NSString stringWithFormat:locFormatString, userinfo]; 173 | break; 174 | } 175 | } 176 | 177 | return descr; 178 | } 179 | 180 | #pragma mark - System Errors 181 | 182 | NSError * cac_OSStatusError( OSStatus code ) { 183 | 184 | NSString *description = cac_systemErrorDescription(code); 185 | NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain 186 | code:code 187 | userInfo:@{ NSLocalizedDescriptionKey : description }]; 188 | return error; 189 | } 190 | 191 | NSString * cac_systemErrorDescription(NSInteger code ) { 192 | 193 | NSString *descr = NSLocalizedStringFromTableInBundle(@"An unknown error occurred.", 194 | @"Localizable", 195 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 196 | @"Error description - Returned if an unknown error occurred."); 197 | 198 | /* Defined in */ 199 | 200 | switch (code) { 201 | 202 | case userCanceledErr: { 203 | descr = NSLocalizedStringFromTableInBundle(@"Die Operation wurde vom Nutzer abgebrochen.", 204 | @"Localizable", 205 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 206 | @"Error description - Returned if the operation was canceled by the user."); 207 | } 208 | break; 209 | 210 | case dskFulErr: { 211 | descr = NSLocalizedStringFromTableInBundle(@"Es ist kein Platz mehr auf dem Laufwerk.", 212 | @"Localizable", 213 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 214 | @"Error description - Returned if there is no space on the disk."); 215 | } 216 | break; 217 | 218 | case nsvErr: { 219 | descr = NSLocalizedStringFromTableInBundle(@"Das Laufwerk konnte nicht gefunden werden.", 220 | @"Localizable", 221 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 222 | @"Error description - Returned if there is no such volume."); 223 | } 224 | break; 225 | 226 | case ioErr: { 227 | descr = NSLocalizedStringFromTableInBundle(@"Beim lesen/schreiben ist ein Fehler aufgetreten.", 228 | @"Localizable", 229 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 230 | @"Error description - Returned if an I/O error occurred."); 231 | } 232 | break; 233 | 234 | 235 | case bdNamErr: { 236 | descr = NSLocalizedStringFromTableInBundle(@"Der Dateiname ist nicht zulässig.", 237 | @"Localizable", 238 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 239 | @"Error description - Returned if a bad file name was passed to the routine."); 240 | } 241 | break; 242 | 243 | case fBsyErr: { 244 | descr = NSLocalizedStringFromTableInBundle(@"Das Volumen kann nicht ausgeworfen werden, weil es von einem anderen Prozess verwendet wird.", 245 | @"Localizable", 246 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 247 | @"Error description - Returned if the file/volume is beeing used by another process."); 248 | } 249 | break; 250 | 251 | case fsDataTooBigErr: { 252 | descr = NSLocalizedStringFromTableInBundle(@"Die Datei oder Partition ist zu groß.", 253 | @"Localizable", 254 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 255 | @"Error description - Returned if the file or volume is too big for the system."); 256 | } 257 | break; 258 | 259 | case volVMBusyErr: { 260 | descr = NSLocalizedStringFromTableInBundle(@"Das Laufwerk kann nicht ausgeworfen werden, weil es von der VM benutzt wird.", 261 | @"Localizable", 262 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 263 | @"Error description - Returned if the volume can't be ejected because it is used by the VM."); 264 | } 265 | break; 266 | 267 | case errFSUnknownCall: { 268 | descr = NSLocalizedStringFromTableInBundle(@"Die Aktion wird von dem Dateisystem nicht unterstützt.", 269 | @"Localizable", 270 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 271 | @"Error description - Returned if the selector is not recognized by the filesystem."); 272 | } 273 | break; 274 | 275 | case errFSNotAFolder: { 276 | descr = NSLocalizedStringFromTableInBundle(@"Das angegebene Objekt ist kein Ordner.", 277 | @"Localizable", 278 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 279 | @"Error description - Returned if a folder was expected and a file was passed."); 280 | } 281 | break; 282 | 283 | case errFSOperationNotSupported: { 284 | descr = NSLocalizedStringFromTableInBundle(@"Die Operation wird von dem Dateisystem nicht unterstützt.", 285 | @"Localizable", 286 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 287 | @"Error description - Returned if the attempted operation is not supported by the filesystem."); 288 | } 289 | break; 290 | 291 | case errFSNotEnoughSpaceForOperation: { 292 | descr = NSLocalizedStringFromTableInBundle(@"Es ist nicht genügend Speicherplatz vorhanden um die Operation auszuführen.", 293 | @"Localizable", 294 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 295 | @"Error description - Returned if there is not enough disk space to perform the requested operation."); 296 | } 297 | break; 298 | 299 | case fsmBusyFFSErr: { 300 | descr = NSLocalizedStringFromTableInBundle(@"Das Laufwerk ist beschäftigt und kann nicht entfernt werden.", 301 | @"Localizable", 302 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 303 | @"Error description - Returned if the file system is busy and cannot be removed."); 304 | } 305 | break; 306 | 307 | case coreFoundationUnknownErr: { 308 | descr = NSLocalizedStringFromTableInBundle(@"Es ist ein unbekannter Fehler im Core Foundation Framework aufgetreten.", 309 | @"Localizable", 310 | [NSBundle bundleWithIdentifier:kCoreAudioConverterIdentifier], 311 | @"Error description - Returned if there occurred an unknown Core Foundation error."); 312 | } 313 | break; 314 | } 315 | 316 | return descr; 317 | } 318 | 319 | #pragma mark - 320 | -------------------------------------------------------------------------------- /CoreAudioConverter/Categories/NSError+Exceptions.h: -------------------------------------------------------------------------------- 1 | /* 2 | * NSError+Exceptions.h 3 | * CoreAudioConverter 4 | * 5 | * Copyright © 2015-2020 Simon Gaus 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | * 20 | */ 21 | 22 | @import Foundation; 23 | 24 | /** 25 | 26 | The Exception categorie adds the capability to create an error object from an NSException object to the NSError class. 27 | 28 | */ 29 | 30 | NS_ASSUME_NONNULL_BEGIN 31 | 32 | @interface NSError (Exception) 33 | #pragma mark - Create an error 34 | ///------------------------------------------- 35 | /// @name Create an error 36 | ///------------------------------------------- 37 | 38 | /** 39 | @brief Creates and initializes an NSError object for a given domain and code the user info will be extracted from a given excepction. 40 | @param exception The exception to use for the error userInfo. 41 | @param domain The error domain. 42 | @param code The error code for the error. 43 | @return An NSError object for domain with the specified error code and the dictionary of arbitrary data userInfo extracted from the exeption. 44 | */ 45 | + (instancetype)errorWithException:(NSException *)exception domain:(NSString *)domain code:(NSInteger)code; 46 | 47 | 48 | @end 49 | 50 | NS_ASSUME_NONNULL_END 51 | -------------------------------------------------------------------------------- /CoreAudioConverter/Categories/NSError+Exceptions.m: -------------------------------------------------------------------------------- 1 | /* 2 | * NSError+Exceptions.m 3 | * CoreAudioConverter 4 | * 5 | * Copyright © 2015-2020 Simon Gaus 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | * 20 | */ 21 | 22 | #import "NSError+Exceptions.h" 23 | 24 | @implementation NSError (Exception) 25 | #pragma mark - Create an error 26 | 27 | + (instancetype)errorWithException:(NSException *)exception domain:(NSString *)domain code:(NSInteger)code { 28 | 29 | NSMutableDictionary * info = [NSMutableDictionary dictionary]; 30 | [info setValue:exception.name forKey:@"MONExceptionName"]; 31 | [info setValue:exception.reason forKey:@"MONExceptionReason"]; 32 | [info setValue:exception.callStackReturnAddresses forKey:@"MONExceptionCallStackReturnAddresses"]; 33 | [info setValue:exception.callStackSymbols forKey:@"MONExceptionCallStackSymbols"]; 34 | [info setValue:exception.userInfo forKey:@"MONExceptionUserInfo"]; 35 | 36 | return [[NSError alloc] initWithDomain:domain 37 | code:code 38 | userInfo:[info copy]]; 39 | } 40 | 41 | #pragma mark - 42 | @end 43 | -------------------------------------------------------------------------------- /CoreAudioConverter/Categories/NSFileManager+FileAccess.h: -------------------------------------------------------------------------------- 1 | /* 2 | * NSFileManager+FileAccess.h 3 | * CoreAudioConverter 4 | * 5 | * Copyright © 2015-2020 Simon Gaus 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | * 20 | */ 21 | 22 | @import Foundation; 23 | 24 | NS_ASSUME_NONNULL_BEGIN 25 | 26 | /** 27 | @brief These constants defines the different file access kinds. The values are taken from . 28 | */ 29 | typedef NS_OPTIONS(NSInteger, AccessKind) { 30 | /// Test for read permission (1<<2) 31 | ReadAccess = R_OK, 32 | /// Test for write permission (1<<1) 33 | WriteAccess = W_OK, 34 | /// Test for execute or search permission (1<<0) 35 | ExecuteAccess = X_OK, 36 | /// Test for existence of file (0) 37 | PathExists = F_OK 38 | }; 39 | 40 | /** 41 | 42 | The FileAccess categorie adds the capability to check for file access to the NSFileManager. 43 | 44 | ## Discussion 45 | This is implemented in a sandboxing friendly way, the sandbox won't be triggered if the calling application checks a file outside of it's sandbox. 46 | 47 | */ 48 | @interface NSFileManager (FileAccess) 49 | #pragma mark - Check file access 50 | ///---------------------------------------------- 51 | /// @name Check file access 52 | ///---------------------------------------------- 53 | 54 | /** 55 | @brief Determine whether a file or folder can be accessed. 56 | @see AccessKind enum for possible values for mode. 57 | @param path The path to the file or folder. 58 | @param mode The access mode to check for. 59 | @return Yes if the file or folder is accessible for the specified access mode, otherwise NO. 60 | */ 61 | - (BOOL)path:(NSString *)path isAccessibleFor:(AccessKind)mode; 62 | 63 | 64 | @end 65 | 66 | NS_ASSUME_NONNULL_END 67 | -------------------------------------------------------------------------------- /CoreAudioConverter/Categories/NSFileManager+FileAccess.m: -------------------------------------------------------------------------------- 1 | /* 2 | * NSFileManager+FileAccess.m 3 | * CoreAudioConverter 4 | * 5 | * Copyright © 2015-2020 Simon Gaus 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | * 20 | */ 21 | 22 | #import "NSFileManager+FileAccess.h" 23 | 24 | @implementation NSFileManager (FileAccess) 25 | #pragma mark - Check file access 26 | 27 | - (BOOL)path:(NSString *)path isAccessibleFor:(AccessKind)mode { 28 | return (access(path.fileSystemRepresentation, (int)mode) == noErr); 29 | } 30 | 31 | #pragma mark - 32 | @end 33 | -------------------------------------------------------------------------------- /CoreAudioConverter/Categories/NSImage+PNGData.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSImage+PNGData.h 3 | // CoreAudioConverter 4 | // 5 | // Created by Simon Gaus on 08.08.16. 6 | // Copyright © 2016 Simon Gaus. All rights reserved. 7 | // 8 | 9 | @import Cocoa; 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | /** 13 | 14 | */ 15 | @interface NSImage (PNGData) 16 | /** 17 | @return 18 | */ 19 | - (NSData *)pngData; 20 | 21 | @end 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /CoreAudioConverter/Categories/NSImage+PNGData.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSImage+PNGData.m 3 | // CoreAudioConverter 4 | // 5 | // Created by Simon Gaus on 08.08.16. 6 | // Copyright © 2016 Simon Gaus. All rights reserved. 7 | // 8 | 9 | #import "NSImage+PNGData.h" 10 | 11 | @implementation NSImage (PNGData) 12 | 13 | - (NSData *)pngData { 14 | 15 | NSEnumerator *enumerator = nil; 16 | NSImageRep *currentRepresentation = nil; 17 | NSBitmapImageRep *bitmapRep = nil; 18 | NSSize size; 19 | 20 | enumerator = [self.representations objectEnumerator]; 21 | while((currentRepresentation = [enumerator nextObject])) { 22 | if([currentRepresentation isKindOfClass:[NSBitmapImageRep class]]) { 23 | bitmapRep = (NSBitmapImageRep *)currentRepresentation; 24 | } 25 | } 26 | 27 | // Create a bitmap representation if one doesn't exist 28 | if(!bitmapRep) { 29 | size = self.size; 30 | [self lockFocus]; 31 | bitmapRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0, 0, size.width, size.height)]; 32 | [self unlockFocus]; 33 | } 34 | 35 | return [bitmapRep representationUsingType:NSPNGFileType properties:@{}]; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /CoreAudioConverter/CoreAudioConverter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CoreAudioConverter.h 3 | * CoreAudioConverter 4 | * 5 | * Copyright © 2015-2020 Simon Gaus 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | * 20 | */ 21 | 22 | #import 23 | 24 | //! Project version number for CoreAudioConverter. 25 | FOUNDATION_EXPORT double CoreAudioConverterVersionNumber; 26 | 27 | //! Project version string for CoreAudioConverter. 28 | FOUNDATION_EXPORT const unsigned char CoreAudioConverterVersionString[]; 29 | 30 | // In this header, you should import all the public headers of your framework using statements like #import 31 | 32 | // Public 33 | #import 34 | #import 35 | #import 36 | #import 37 | -------------------------------------------------------------------------------- /CoreAudioConverter/Decode/CADecoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CADecoder.h 3 | * CoreAudioConverter 4 | * 5 | * Copyright © 2015-2020 Simon Gaus 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | * 20 | */ 21 | 22 | @import Cocoa; 23 | @import CoreAudio; 24 | 25 | @class CircularBuffer; 26 | 27 | /** 28 | 29 | An CADecoder object can provide audio data from audio files. 30 | 31 | Supported file formats: 32 | 33 | - Audio Interchange File Format 34 | - Apple Lossless Audio Codec 35 | - Advanced Audio Coding 36 | 37 | */ 38 | 39 | NS_ASSUME_NONNULL_BEGIN 40 | 41 | @interface CADecoder : NSObject 42 | #pragma mark - Initialize a decoder 43 | ///--------------------------------------------------- 44 | /// @name Initialize a decoder 45 | ///--------------------------------------------------- 46 | 47 | /** 48 | @brief Creates and returns a decoder object for the specified audio file. 49 | 50 | Example usage: 51 | 52 | NSError *error; 53 | CADecoder *decoder = [CADecoder decoderForFile:fileUrl error:&error]; 54 | if (!decoder) { 55 | // Handle error 56 | 57 | } 58 | // do stuff with the decoder... 59 | AudioStreamBasicDescription audioDescr = decoder.pcmFormat; 60 | 61 | @param fileUrl The fileURL to the file to decode. 62 | @param error The error that occurred while trying to initialize the decoder. 63 | @return An initialized CADecoder object or nil. 64 | */ 65 | + (nullable instancetype)decoderForFile:(NSURL *)fileUrl error:(NSError **)error; 66 | 67 | 68 | #pragma mark - Properties 69 | ///----------------------------------- 70 | /// @name Properties 71 | ///----------------------------------- 72 | 73 | /** 74 | The format of PCM data provided by the source file. 75 | */ 76 | @property (nonatomic, readonly) AudioStreamBasicDescription pcmFormat; 77 | /** 78 | Returns the length in sample frames of the decoders associated audio file. 79 | */ 80 | @property (nonatomic, readonly) SInt64 totalFrames; 81 | 82 | 83 | #pragma mark - Reading audio into a buffer 84 | ///-------------------------------------------------------------- 85 | /// @name Reading audio into a buffer 86 | ///-------------------------------------------------------------- 87 | 88 | /** 89 | @brief Reads a chunk of PCM input and let the bufferList point to it. 90 | @param bufferList A pointer to hold audio data chunk 91 | @param frameCount Position in the PCM input 92 | @return Will return Zero(0) on failure. 93 | */ 94 | - (UInt32)readAudio:(AudioBufferList *)bufferList frameCount:(UInt32)frameCount; 95 | 96 | 97 | #pragma mark - Supported Audio Extensions 98 | ///------------------------------------------------------------- 99 | /// @name Supported Audio Extensions 100 | ///------------------------------------------------------------- 101 | 102 | /** 103 | @brief Return an array of valid audio file extensions recognized by Core Audio. 104 | @return The supported audio extensions as strings, or nil if an error occures. 105 | */ 106 | + (nullable NSArray *)supportedAudioExtensions; 107 | 108 | 109 | @end 110 | 111 | NS_ASSUME_NONNULL_END 112 | -------------------------------------------------------------------------------- /CoreAudioConverter/Decode/CADecoder.m: -------------------------------------------------------------------------------- 1 | /* 2 | * CADecoder.m 3 | * CoreAudioConverter 4 | * 5 | * Copyright © 2015-2020 Simon Gaus 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | * 20 | */ 21 | 22 | #import "CADecoder.h" 23 | 24 | @import AudioToolbox.AudioFormat; 25 | @import AudioToolbox.ExtendedAudioFile; 26 | 27 | /* Circular Buffer */ 28 | #import "CircularBuffer.h" 29 | 30 | /* Logging */ 31 | #import "CACDebug.h" 32 | 33 | /* Custom Error */ 34 | #import "CACError.h" 35 | 36 | #pragma mark - CATEGORIES 37 | 38 | 39 | @interface CADecoder (/* Private */) 40 | 41 | @property (nonatomic, readwrite) SInt64 currentFrame; 42 | @property (nonatomic, strong) CircularBuffer *pcmBuffer; 43 | @property (nonatomic, strong) NSURL *fileUrl; 44 | @property (nonatomic, readwrite) ExtAudioFileRef extAudioFile; 45 | @property (nonatomic, readwrite) AudioStreamBasicDescription pcmFormat; 46 | 47 | @end 48 | 49 | 50 | #pragma mark - IMPLEMENTATION 51 | 52 | 53 | @implementation CADecoder 54 | #pragma mark - Object creation 55 | 56 | + (nullable instancetype)decoderForFile:(NSURL *)fileUrl error:(NSError * __autoreleasing *)error { 57 | 58 | CADecoder *result = nil; 59 | 60 | // Create the source based on the file's extension 61 | NSArray *coreAudioExtensions = [CADecoder supportedAudioExtensions]; 62 | NSString *extension = [[fileUrl pathExtension] lowercaseString]; 63 | 64 | // format supported 65 | if ([coreAudioExtensions containsObject:extension]) { 66 | 67 | result = [[CADecoder alloc] initWithFile:fileUrl error:(NSError **)error]; 68 | if (!result) { 69 | 70 | if (!error) { 71 | NSError *newError = cac_error(CACFailedToCreateDecoder, fileUrl.lastPathComponent); 72 | if (error != NULL) *error = newError; 73 | } 74 | 75 | return nil; 76 | } 77 | } 78 | // format not supported 79 | else { 80 | NSError *newError = cac_error(CACFileFormatNotSupported, fileUrl.lastPathComponent); 81 | if (error != NULL) *error = newError; 82 | } 83 | 84 | return result; 85 | } 86 | 87 | - (nullable instancetype)initWithFile:(NSURL *)fileUrl error:(NSError * __autoreleasing *)error { 88 | 89 | if (!fileUrl) return nil; 90 | 91 | self = [super init]; 92 | 93 | if (self) { 94 | 95 | _pcmBuffer = [[CircularBuffer alloc] init]; 96 | if (!_pcmBuffer) { 97 | NSError *newError = cac_error(CACMemoryAllocationFailed, nil); 98 | if (error != NULL) *error = newError; 99 | return nil; 100 | } 101 | _fileUrl = fileUrl; 102 | 103 | __unused OSStatus result = ExtAudioFileOpenURL((__bridge CFURLRef _Nonnull)(fileUrl), &_extAudioFile); 104 | if (result != noErr) { 105 | CFStringRef descr = UTCreateStringForOSType(result); 106 | CACLog(CACDebugLevelError, @"ExtAudioFileOpen failed: %@", descr); 107 | if (descr != NULL) CFRelease(descr); 108 | 109 | NSError *newError = cac_error(CACFailedToOpenInputFile, fileUrl.lastPathComponent); 110 | if (error != NULL) *error = newError; 111 | return nil; 112 | } 113 | 114 | // Query file type 115 | UInt32 dataSize = sizeof(AudioStreamBasicDescription); 116 | result = ExtAudioFileGetProperty(_extAudioFile, kExtAudioFileProperty_FileDataFormat, &dataSize, &_pcmFormat); 117 | if (result != noErr) { 118 | CFStringRef descr = UTCreateStringForOSType(result); 119 | CACLog(CACDebugLevelError, @"AudioFileGetProperty failed: %@", descr); 120 | if (descr != NULL) CFRelease(descr); 121 | 122 | NSError *newError = cac_error(CACUnknownFileType, fileUrl.lastPathComponent); 123 | if (error != NULL) *error = newError; 124 | return nil; 125 | } 126 | 127 | _pcmFormat.mFormatID = kAudioFormatLinearPCM; 128 | _pcmFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsPacked; 129 | 130 | // For alac the source bit depth is encoded in the format flag 131 | if(kAudioFormatAppleLossless == _pcmFormat.mFormatID) { 132 | 133 | switch (_pcmFormat.mFormatFlags) { 134 | case kAppleLosslessFormatFlag_16BitSourceData: 135 | _pcmFormat.mBitsPerChannel = 16; 136 | break; 137 | case kAppleLosslessFormatFlag_24BitSourceData: 138 | _pcmFormat.mBitsPerChannel = 24; 139 | break; 140 | case kAppleLosslessFormatFlag_32BitSourceData: 141 | _pcmFormat.mBitsPerChannel = 32; 142 | break; 143 | default: 144 | _pcmFormat.mBitsPerChannel = 16; 145 | break; 146 | } 147 | } 148 | else { 149 | 150 | // Preserve mSampleRate and mChannelsPerFrame 151 | _pcmFormat.mBitsPerChannel = (0 == _pcmFormat.mBitsPerChannel ? 16 : _pcmFormat.mBitsPerChannel); 152 | 153 | _pcmFormat.mBytesPerPacket = (_pcmFormat.mBitsPerChannel / 8) * _pcmFormat.mChannelsPerFrame; 154 | _pcmFormat.mFramesPerPacket = 1; 155 | _pcmFormat.mBytesPerFrame = _pcmFormat.mBytesPerPacket * _pcmFormat.mFramesPerPacket; 156 | } 157 | 158 | // Tell the extAudioFile the format we'd like for data 159 | result = ExtAudioFileSetProperty(_extAudioFile, kExtAudioFileProperty_ClientDataFormat, sizeof(_pcmFormat), &_pcmFormat); 160 | if (result != noErr) { 161 | 162 | CFStringRef descr = UTCreateStringForOSType(result); 163 | CACLog(CACDebugLevelError, @"ExtAudioFileSetProperty failed: %@", descr); 164 | if (descr != NULL) CFRelease(descr); 165 | return nil; 166 | } 167 | } 168 | 169 | return self; 170 | } 171 | 172 | - (void)dealloc { 173 | 174 | if (_extAudioFile) { 175 | OSStatus result = ExtAudioFileDispose(_extAudioFile); 176 | if (result != noErr) { 177 | CFStringRef descr = UTCreateStringForOSType(result); 178 | CACLog(CACDebugLevelError, @"ExtAudioFileDispose failed: %@", descr); 179 | if (descr != NULL) CFRelease(descr); 180 | } 181 | } 182 | } 183 | 184 | #pragma mark - Main Methodes 185 | 186 | - (UInt32)readAudio:(AudioBufferList *)bufferList frameCount:(UInt32)frameCount { 187 | 188 | if (bufferList == NULL) { 189 | CACLog(CACDebugLevelError, @"An error occurred during decoding."); 190 | return 0; 191 | } 192 | if (bufferList->mNumberBuffers <= 0) { 193 | CACLog(CACDebugLevelError, @"An error occurred during decoding."); 194 | return 0; 195 | } 196 | if (frameCount <= 0) { return 0; } 197 | 198 | UInt32 framesRead = 0; 199 | UInt32 byteCount = frameCount * self.pcmFormat.mBytesPerPacket; 200 | UInt32 bytesRead = 0; 201 | 202 | if (byteCount > bufferList->mBuffers[0].mDataByteSize) { 203 | CACLog(CACDebugLevelError, @"An error occurred during decoding."); 204 | return 0; 205 | } 206 | 207 | // If there aren't enough bytes in the buffer, fill it as much as possible 208 | if([[self pcmBuffer] bytesAvailable] < byteCount) { 209 | 210 | BOOL erfolg = [self fillPCMBuffer]; 211 | if (!erfolg) { 212 | CACLog(CACDebugLevelError, @"An error occurred during decoding."); 213 | return 0; 214 | } 215 | } 216 | 217 | // If there still aren't enough bytes available, return what we have 218 | if([self.pcmBuffer bytesAvailable] < byteCount) 219 | byteCount = (UInt32)[self.pcmBuffer bytesAvailable]; 220 | 221 | bytesRead = (UInt32)[[self pcmBuffer] getData:bufferList->mBuffers[0].mData byteCount:byteCount]; 222 | bufferList->mBuffers[0].mNumberChannels = [self pcmFormat].mChannelsPerFrame; 223 | bufferList->mBuffers[0].mDataByteSize = bytesRead; 224 | framesRead = bytesRead / [self pcmFormat].mBytesPerFrame; 225 | 226 | // Update internal state 227 | _currentFrame += framesRead; 228 | 229 | return framesRead; 230 | } 231 | 232 | - (SInt64)totalFrames { 233 | 234 | __unused OSStatus result; 235 | UInt32 dataSize; 236 | SInt64 frameCount; 237 | 238 | dataSize = sizeof(frameCount); 239 | result = ExtAudioFileGetProperty(_extAudioFile, kExtAudioFileProperty_FileLengthFrames, &dataSize, &frameCount); 240 | 241 | if (result != noErr) { 242 | CFStringRef descr = UTCreateStringForOSType(result); 243 | CACLog(CACDebugLevelError, @"AudioFileGetProperty failed: %@", descr); 244 | if (descr != NULL) CFRelease(descr); 245 | return 0; 246 | } 247 | 248 | return frameCount; 249 | } 250 | 251 | - (BOOL)fillPCMBuffer { 252 | 253 | CircularBuffer *buffer = self.pcmBuffer; 254 | __unused OSStatus result; 255 | AudioBufferList bufferList; 256 | UInt32 frameCount; 257 | 258 | bufferList.mNumberBuffers = 1; 259 | bufferList.mBuffers[0].mNumberChannels = self.pcmFormat.mChannelsPerFrame; 260 | // type is spezified return type in circular buffer 261 | uint8_t *data = [buffer exposeBufferForWriting]; 262 | if (data == nil) { 263 | CACLog(CACDebugLevelError, @"Failed to expose buffer for writing."); 264 | return NO; 265 | } 266 | bufferList.mBuffers[0].mData = data; 267 | 268 | bufferList.mBuffers[0].mDataByteSize = (UInt32)[buffer freeSpaceAvailable]; 269 | frameCount = bufferList.mBuffers[0].mDataByteSize / self.pcmFormat.mBytesPerFrame; 270 | result = ExtAudioFileRead(_extAudioFile, &frameCount, &bufferList); 271 | 272 | if (result != noErr) { 273 | CFStringRef descr = UTCreateStringForOSType(result); 274 | CACLog(CACDebugLevelError, @"ExtAudioFileRead failed: %@", descr); 275 | if (descr != NULL) CFRelease(descr); 276 | return NO; 277 | } 278 | 279 | if ((bufferList.mBuffers[0].mDataByteSize) != (frameCount * self.pcmFormat.mBytesPerFrame)) { 280 | CACLog(CACDebugLevelError, @"mismatch"); 281 | return NO; 282 | } 283 | 284 | [buffer wroteBytes:bufferList.mBuffers[0].mDataByteSize]; 285 | return YES; 286 | } 287 | 288 | #pragma mark - Helper Methodes 289 | 290 | + (NSArray *)supportedAudioExtensions { 291 | 292 | NSArray *coreAudioExtensions; 293 | UInt32 size = sizeof(coreAudioExtensions); 294 | __unused OSStatus err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_AllExtensions, 0, NULL, &size, &coreAudioExtensions); 295 | 296 | if (err != noErr) { 297 | 298 | CFStringRef descr = UTCreateStringForOSType(err); 299 | CACLog(CACDebugLevelError, @"Failed to get supported Core Audio Extensions. Failure reason: %@", descr); 300 | if (descr != NULL) CFRelease(descr); 301 | } 302 | return coreAudioExtensions; 303 | } 304 | 305 | #pragma mark - 306 | @end 307 | -------------------------------------------------------------------------------- /CoreAudioConverter/Encode/EncoderTask.h: -------------------------------------------------------------------------------- 1 | /* 2 | * EncoderTask.h 3 | * CoreAudioConverter 4 | * 5 | * Copyright © 2016 Simon Gaus 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | * 20 | */ 21 | 22 | @import Foundation; 23 | 24 | /** 25 | 26 | An EncoderTask object represents an audio file to convert. 27 | 28 | ## Notes 29 | It would have been enough to specify an input and output URL to give the encoder enough informations for the converting. 30 | I decided to use a temporary url, as there are various cases where you want to encode the file to a temporary location and than later move the file to their final location. It is possible to skip that step by intitializing an EncoderTask object with nil as argument for the tempURL, than the file will be encoded directly to the location the outputURL points to. 31 | 32 | */ 33 | 34 | NS_ASSUME_NONNULL_BEGIN 35 | 36 | @interface EncoderTask : NSObject 37 | #pragma mark - Create a task 38 | ///---------------------------------------- 39 | /// @name Create a task 40 | ///---------------------------------------- 41 | 42 | /** 43 | @brief Creates and returns an EncoderTask object initialized with the provided input, output and temporary file URL. 44 | @warning The encoders will use the tempURL as destination for the encoded file. If this is initialized with nil, tempURL will return outputURL. 45 | @param inputURL The fileURL to the file that should be converted. 46 | @param outputURL The fileURL to the output file. 47 | @param tempURL The URL to a temporary location for the output file. 48 | @return An initialized EncoderTask object or nil. 49 | */ 50 | + (nullable instancetype)taskWithInputURL:(NSURL *)inputURL 51 | outputURL:(NSURL *)outputURL 52 | temporaryURL:(nullable NSURL *)tempURL; 53 | 54 | 55 | #pragma mark - Properties 56 | ///----------------------------------- 57 | /// @name Properties 58 | ///----------------------------------- 59 | 60 | /** 61 | @brief The fileURL to the file that should be converted. 62 | @warning In a sandboxed application this needs to be a security-scoped URL, as -startAccessingSecurityScopedResource will be send to it. 63 | @see https://developer.apple.com/reference/foundation/nsurl/1417051-startaccessingsecurityscopedreso?language=objc for more information. 64 | */ 65 | @property (nonatomic, readonly) NSURL *inputURL; 66 | /** 67 | @brief The fileURL to the output file 68 | @see Related: tempURL 69 | */ 70 | @property (nonatomic, readonly) NSURL *outputURL; 71 | /** 72 | @brief The URL to a temporary location for the output file. 73 | @warning If this is set to nil in +taskWithInputURL:outputURL:temporaryURL: this property will return outputURL. 74 | */ 75 | @property (nonatomic, readonly) NSURL *tempURL; 76 | 77 | 78 | @end 79 | 80 | NS_ASSUME_NONNULL_END 81 | -------------------------------------------------------------------------------- /CoreAudioConverter/Encode/EncoderTask.m: -------------------------------------------------------------------------------- 1 | /* 2 | * EncoderTask.m 3 | * CoreAudioConverter 4 | * 5 | * Copyright © 2016 Simon Gaus 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | * 20 | */ 21 | 22 | #import "EncoderTask.h" 23 | #pragma mark - CATEGORIES 24 | 25 | 26 | @interface EncoderTask (/* Private */) 27 | 28 | @property (nonatomic, strong) NSURL *tempURL; 29 | @property (nonatomic, strong) NSURL *inputURL; 30 | @property (nonatomic, strong) NSURL *outputURL; 31 | 32 | @end 33 | 34 | 35 | #pragma mark - IMPLEMENTATION 36 | 37 | 38 | @implementation EncoderTask 39 | #pragma mark - Create a task 40 | 41 | + (nullable instancetype)taskWithInputURL:(NSURL *)inputURL 42 | outputURL:(NSURL *)outputURL 43 | temporaryURL:(nullable NSURL *)tempURL { 44 | 45 | return [[[self class] alloc] initWithInputURL:inputURL 46 | outputURL:outputURL 47 | temporaryURL:tempURL]; 48 | } 49 | 50 | - (instancetype)initWithInputURL:(NSURL *)inputURL 51 | outputURL:(NSURL *)outputURL 52 | temporaryURL:(nullable NSURL *)tempURL { 53 | 54 | if (!inputURL || !outputURL) { 55 | NSLog(@"Called %@ with nil argument.", NSStringFromSelector(_cmd)); 56 | return nil; 57 | } 58 | 59 | self = [super init]; 60 | if (self) { 61 | 62 | _inputURL = inputURL; 63 | _outputURL = outputURL; 64 | _tempURL = tempURL; 65 | } 66 | return self; 67 | } 68 | 69 | #pragma mark - Properties 70 | 71 | - (NSURL *)tempURL { 72 | // if tempURL isnt set, just return outputURL. 73 | return (_tempURL) ? _tempURL : self.outputURL; 74 | } 75 | 76 | #pragma mark - 77 | @end 78 | -------------------------------------------------------------------------------- /CoreAudioConverter/Encode/MP3Encoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MP3Encoder.h 3 | * CoreAudioConverter 4 | * 5 | * Copyright © 2016-2019 Simon Gaus 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | * 20 | */ 21 | 22 | @import Cocoa; 23 | 24 | @class EncoderTask; 25 | 26 | #import "MP3EncoderDelegateProtocol.h" 27 | 28 | /** 29 | 30 | An MP3Encoder object can convert various audio file formats to MPEG Audio Layer III, 31 | more commonly referred to as MP3. 32 | 33 | */ 34 | 35 | NS_ASSUME_NONNULL_BEGIN 36 | 37 | @interface MP3Encoder : NSObject 38 | 39 | #pragma mark - Initializing an encoder object 40 | ///------------------------------------------------------------------- 41 | /// @name Initializing an encoder object 42 | ///------------------------------------------------------------------- 43 | 44 | /** 45 | @brief Returns an MP3Encoder object initialized with the given delegate. This is the designated initializer. 46 | @param aDelegate The encoders delegate. 47 | @return A MP3Encoder object initialized with aDelegate. If aDelegate is nil or lame coulden't be initialized, returns nil. 48 | */ 49 | - (nullable instancetype)initWithDelegate:(NSObject *)aDelegate NS_DESIGNATED_INITIALIZER; 50 | 51 | 52 | #pragma mark - Executing an encoder task 53 | ///----------------------------------------------------------- 54 | /// @name Executing an encoder task 55 | ///----------------------------------------------------------- 56 | 57 | /** 58 | @brief Executes the given encoder task. 59 | @param task The encoder task to execute. 60 | @param error May contain an error, desccribing the failure reason. 61 | @return YES if the executing was successfull, otherwise NO. 62 | */ 63 | - (BOOL)executeTask:(EncoderTask *)task error:(NSError * _Nullable *)error; 64 | 65 | 66 | @end 67 | 68 | NS_ASSUME_NONNULL_END 69 | -------------------------------------------------------------------------------- /CoreAudioConverter/Encode/MP3Encoder.m: -------------------------------------------------------------------------------- 1 | /* 2 | * MP3Encoder.m 3 | * CoreAudioConverter 4 | * 5 | * Copyright © 2016-2019 Simon Gaus 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | * 20 | */ 21 | 22 | #import "MP3Encoder.h" 23 | 24 | @import AudioFileTagger; // for MP3Tagger 25 | 26 | /* LAME encoding */ 27 | @import lame; 28 | 29 | /* Encoders Task */ 30 | #import "EncoderTask.h" 31 | 32 | /* Core Audio Decoder */ 33 | #import "CADecoder.h" 34 | 35 | /* Check access rights for files&folders */ 36 | #import "NSFileManager+FileAccess.h" 37 | 38 | /* Logging */ 39 | #import "CACDebug.h" 40 | 41 | /* Custom Error */ 42 | #import "CACError.h" 43 | 44 | #pragma mark - CONSTANTS 45 | 46 | 47 | /// The file extension of a MP3 file. 48 | static NSString * const kFileExtension = @"mp3"; 49 | /// The number of bits for checking the min. disc space. 50 | static NSUInteger const kMinFreeDiskSpace = 100000000; 51 | 52 | 53 | #pragma mark - CATEGORIES 54 | 55 | 56 | @interface MP3Encoder (/* Private */) 57 | 58 | @property (nonatomic, readwrite) FILE *out; 59 | @property (nonatomic, readwrite) UInt32 sourceBitsPerChannel; 60 | @property (nonatomic, readwrite) lame_global_flags *gfp; 61 | @property (nonatomic, assign) NSObject *delegate; 62 | @property (nonatomic, strong) NSURL *secureURLIn; 63 | @property (nonatomic, strong) NSURL *secureURLOut; 64 | @property (nonatomic, readwrite) BOOL fileProperlyEncoded; 65 | @property (nonatomic, readonly) NSFileManager *fileManager; 66 | 67 | @end 68 | 69 | 70 | #pragma mark - IMPLEMENTATION 71 | 72 | 73 | @implementation MP3Encoder 74 | #pragma mark - Initializing an encoder object 75 | 76 | - (nullable instancetype)initWithDelegate:(NSObject *)aDelegate { 77 | 78 | self = [super init]; 79 | if(self) { 80 | 81 | if (!aDelegate) { 82 | return nil; 83 | } 84 | _delegate = aDelegate; 85 | 86 | _gfp = lame_init(); 87 | if (_gfp == NULL) { 88 | return nil; 89 | } 90 | } 91 | 92 | return self; 93 | } 94 | 95 | - (instancetype)init { 96 | NSAssert(false, @"Unavailable, use `-initWithDelegate:` instead."); 97 | return [self initWithDelegate:(NSObject *)[NSObject new]]; 98 | } 99 | 100 | - (void)dealloc { 101 | // free lame 102 | lame_close(_gfp); 103 | } 104 | 105 | #pragma mark - API Methodes 106 | 107 | - (BOOL)executeTask:(EncoderTask *)task error:(NSError * __autoreleasing *)error { 108 | 109 | if ([self.delegate cancel]) return YES; 110 | 111 | FILE *file = NULL; 112 | int result; 113 | AudioBufferList bufferList; 114 | ssize_t bufferLen = 0; 115 | UInt32 bufferByteSize = 0; 116 | SInt64 totalFrames, framesToRead; 117 | UInt32 frameCount; 118 | self.fileProperlyEncoded = NO; 119 | 120 | @try { 121 | 122 | bufferList.mBuffers[0].mData = NULL; 123 | 124 | // prepare lame settings 125 | [self parseSettings]; 126 | 127 | // Setup input url 128 | self.secureURLIn = task.inputURL; 129 | self.secureURLOut = task.tempURL; 130 | 131 | // start accessing it 132 | if (![self.secureURLIn startAccessingSecurityScopedResource] && 133 | ![self.fileManager path:self.secureURLIn.path isAccessibleFor:ReadAccess]){ 134 | 135 | NSString *filePath = self.secureURLIn.path; 136 | NSError *accessError = cac_error(CACFilePermissionDenied, filePath); 137 | if (error != NULL) *error = accessError; 138 | return NO; 139 | } 140 | 141 | // check if there is enough disc space to write the output file 142 | if (![self enoughFreeSpaceToConvert:self.secureURLOut.URLByDeletingLastPathComponent]) { 143 | 144 | NSString *filePath = self.secureURLIn.lastPathComponent; 145 | NSError *discSpaceError = cac_error(CACFilePermissionDenied, filePath); 146 | if (error != NULL) *error = discSpaceError; 147 | return NO; 148 | } 149 | 150 | // Create the appropriate kind of decoder 151 | NSError *decoderError = nil; 152 | CADecoder *decoder = [CADecoder decoderForFile:_secureURLIn error:&decoderError]; 153 | if (!decoder) { 154 | CACLog(CACDebugLevelError, @"Unable to load decoder."); 155 | if (decoderError && error != NULL) *error = decoderError; 156 | return NO; 157 | } 158 | 159 | if ([decoder pcmFormat].mChannelsPerFrame > 2) { 160 | CACLog(CACDebugLevelError, @"LAME only supports one or two channel input."); 161 | NSString *userInfo = [NSString stringWithFormat:@"File:%@|Channels:%u", _secureURLIn.path, (unsigned int)[decoder pcmFormat].mChannelsPerFrame]; 162 | if (error != NULL) *error = cac_error(CACTooMayChannels, userInfo); 163 | return NO; 164 | } 165 | 166 | _sourceBitsPerChannel = [decoder pcmFormat].mBitsPerChannel; 167 | totalFrames = [decoder totalFrames]; 168 | framesToRead = totalFrames; 169 | 170 | // Set up the AudioBufferList 171 | bufferList.mNumberBuffers = 1; 172 | bufferList.mBuffers[0].mData = NULL; 173 | bufferList.mBuffers[0].mNumberChannels = [decoder pcmFormat].mChannelsPerFrame; 174 | 175 | // Allocate the buffer that will hold the interleaved audio data 176 | bufferLen = 1024; 177 | switch([decoder pcmFormat].mBitsPerChannel) { 178 | 179 | case 8: 180 | case 24: 181 | bufferList.mBuffers[0].mData = calloc(bufferLen, sizeof(int8_t)); 182 | bufferList.mBuffers[0].mDataByteSize = (UInt8)bufferLen * sizeof(int8_t); 183 | break; 184 | 185 | case 16: 186 | bufferList.mBuffers[0].mData = calloc(bufferLen, sizeof(int16_t)); 187 | bufferList.mBuffers[0].mDataByteSize = (UInt16)bufferLen * sizeof(int16_t); 188 | break; 189 | 190 | case 32: 191 | bufferList.mBuffers[0].mData = calloc(bufferLen, sizeof(int32_t)); 192 | bufferList.mBuffers[0].mDataByteSize = (UInt32)bufferLen * sizeof(int32_t); 193 | break; 194 | 195 | default: { 196 | NSString *userInfo = [NSString stringWithFormat:@"File:%@|SampleSize:%u", _secureURLIn.lastPathComponent, (unsigned int)[decoder pcmFormat].mBitsPerChannel]; 197 | NSError *newError = cac_error(CACUnsupportedSampleSize, userInfo); 198 | if (error != NULL) *error = newError; 199 | return NO; 200 | } 201 | } 202 | 203 | bufferByteSize = bufferList.mBuffers[0].mDataByteSize; 204 | if (bufferList.mBuffers[0].mData == NULL) { 205 | NSError *newError = cac_error(CACMemoryAllocationFailed, nil); 206 | if (error != NULL) *error = newError; 207 | return NO; 208 | } 209 | 210 | // Initialize the LAME encoder 211 | lame_set_num_channels(_gfp, [decoder pcmFormat].mChannelsPerFrame); 212 | lame_set_in_samplerate(_gfp, [decoder pcmFormat].mSampleRate); 213 | 214 | result = lame_init_params(_gfp); 215 | if (result != noErr) { 216 | NSString *userInfo = [NSString stringWithFormat:@"%i", result]; 217 | NSError *newError = cac_error(CACLameSettingsInitFailed, userInfo); 218 | if (error != NULL) *error = newError; 219 | return NO; 220 | } 221 | 222 | // touch output file (dont cancle here, because of posix file permissions) 223 | [self touchOutputFile:_secureURLOut]; 224 | 225 | // Open the output file 226 | _out = fopen(_secureURLOut.fileSystemRepresentation, "w"); 227 | if (_out == NULL) { 228 | NSString *userInfo = [NSString stringWithFormat:@"%s", _secureURLOut.fileSystemRepresentation]; 229 | NSError *newError = cac_error(CACOutputAccessFailed, userInfo); 230 | if (error != NULL) *error = newError; 231 | return NO; 232 | } 233 | 234 | // Iterate over the data and encode it 235 | for(;;) { 236 | 237 | // check if we should cancel 238 | if ([self.delegate cancel]) return YES; 239 | 240 | // Set up the buffer parameters 241 | bufferList.mBuffers[0].mNumberChannels = [decoder pcmFormat].mChannelsPerFrame; 242 | bufferList.mBuffers[0].mDataByteSize = bufferByteSize; 243 | frameCount = bufferList.mBuffers[0].mDataByteSize / [decoder pcmFormat].mBytesPerFrame; 244 | 245 | // Read a chunk of PCM input 246 | frameCount = [decoder readAudio:&bufferList frameCount:frameCount]; 247 | 248 | // We're finished (or decoder failed) if no frames were returned 249 | if(frameCount == 0) { 250 | break; 251 | } 252 | 253 | // Encode the PCM data 254 | NSError *chunkError = nil; 255 | BOOL result = [self encodeChunk:&bufferList frameCount:frameCount error:&chunkError]; 256 | if (!result) { 257 | if (chunkError) *error = chunkError; 258 | return NO; 259 | } 260 | } 261 | 262 | // Flush the last MP3 frames (maybe) 263 | NSError *flushError; 264 | if (![self finishEncodeWithError:&flushError]) { 265 | if (flushError && error != NULL) *error = flushError; 266 | return NO; 267 | } 268 | 269 | // Close the output file 270 | result = fclose(_out); 271 | if (result != noErr) { 272 | NSError *newError = cac_error(CACOutputClosingFailed, [_secureURLOut.path copy]); 273 | if (error != NULL) *error = newError; 274 | return NO; 275 | } 276 | _out = NULL; 277 | 278 | // Write the Xing VBR tag 279 | file = fopen(_secureURLOut.fileSystemRepresentation, "r+"); 280 | if (file == NULL) { 281 | 282 | NSError *newError = cac_error(CACOutputAccessFailed, _secureURLOut.path); 283 | if (error != NULL) *error = newError; 284 | return NO; 285 | } 286 | // hmmm... 287 | lame_mp3_tags_fid(_gfp, file); 288 | 289 | self.fileProperlyEncoded = YES; 290 | 291 | return YES; 292 | } 293 | 294 | @catch(NSException *exception) { 295 | 296 | CACLog(CACDebugLevelError, @"Exception during encoding:%@", exception); 297 | } 298 | 299 | @finally { 300 | 301 | NSException *exception; 302 | 303 | // Close the output file if not already closed 304 | if(NULL != _out && EOF == fclose(_out)) { 305 | exception = [NSException exceptionWithName:@"IOException" 306 | reason:NSLocalizedStringFromTable(@"Unable to close the output file.", @"Exceptions", @"") 307 | userInfo:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:[NSNumber numberWithInt:errno], [NSString stringWithCString:strerror(errno) encoding:NSASCIIStringEncoding], nil] forKeys:[NSArray arrayWithObjects:@"errorCode", @"errorString", nil]]]; 308 | CACLog(CACDebugLevelError, @"%@", exception); 309 | } 310 | 311 | // And close the other output file 312 | if(NULL != file && EOF == fclose(file)) { 313 | exception = [NSException exceptionWithName:@"IOException" 314 | reason:NSLocalizedStringFromTable(@"Unable to close the output file.", @"Exceptions", @"") 315 | userInfo:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:[NSNumber numberWithInt:errno], [NSString stringWithCString:strerror(errno) encoding:NSASCIIStringEncoding], nil] forKeys:[NSArray arrayWithObjects:@"errorCode", @"errorString", nil]]]; 316 | CACLog(CACDebugLevelError, @"%@", exception); 317 | } 318 | 319 | // free buffer 320 | free(bufferList.mBuffers[0].mData); 321 | ///!!!: Implement tagger failing handling ... 322 | // the file was properly encoded 323 | if (self.fileProperlyEncoded) { 324 | 325 | Metadata *meta = [[Metadata alloc] initWithMetadataFromFile:_secureURLIn]; 326 | if (meta) { 327 | 328 | MP3Tagger *tagger = [MP3Tagger taggerWithMetadata:meta]; 329 | 330 | if (![tagger tagFile:_secureURLOut]) { 331 | NSLog(@"Failed to tag file: %@", _secureURLOut.lastPathComponent); 332 | } 333 | } else { 334 | NSLog(@"Failed to extract metadata from file: %@", _secureURLIn.lastPathComponent); 335 | } 336 | } 337 | 338 | [_secureURLIn stopAccessingSecurityScopedResource]; 339 | } 340 | } 341 | 342 | #pragma mark - Helper Methodes 343 | 344 | - (BOOL)enoughFreeSpaceToConvert:(NSURL *)destFolder { 345 | return ([self availableDiscSpace:destFolder] > kMinFreeDiskSpace); 346 | } 347 | 348 | - (unsigned long long)availableDiscSpace:(NSURL *)folderPath { 349 | 350 | NSString *path = folderPath.path; 351 | if (!path) { 352 | CACLog(CACDebugLevelError, @"Failed to get temporary directory."); 353 | return 0; 354 | } 355 | 356 | NSError *error = nil; 357 | NSDictionary *attr = [[NSFileManager defaultManager] attributesOfFileSystemForPath:path error:&error]; 358 | if (!attr) { 359 | if (error) { 360 | CACLog(CACDebugLevelError, @"%@", error.localizedDescription); 361 | } 362 | return 0; 363 | } 364 | 365 | NSNumber *space = [attr valueForKey:NSFileSystemFreeSize]; 366 | if (!space) { 367 | 368 | CACLog(CACDebugLevelError, @"Failed to get available disk space."); 369 | return 0; 370 | } 371 | 372 | return space.unsignedLongLongValue; 373 | } 374 | 375 | #pragma mark - 376 | 377 | - (void)parseSettings { 378 | // Set encoding properties 379 | lame_set_mode(_gfp, JOINT_STEREO); 380 | // quality 381 | lame_set_quality(_gfp, (int)[self.delegate quality]); 382 | // Target is bitrate 383 | lame_set_brate(_gfp, (int)[self.delegate bitrate]); 384 | } 385 | 386 | - (BOOL)encodeChunk:(const AudioBufferList *)chunk 387 | frameCount:(UInt32)frameCount 388 | error:(NSError * __autoreleasing *)error { 389 | 390 | unsigned char *buffer = NULL; 391 | unsigned bufferLen = 0; 392 | 393 | void **channelBuffers = NULL; 394 | short **channelBuffers16 = NULL; 395 | long **channelBuffers32 = NULL; 396 | 397 | int8_t *buffer8 = NULL; 398 | int16_t *buffer16 = NULL; 399 | int32_t *buffer32 = NULL; 400 | 401 | int32_t constructedSample; 402 | 403 | int result; 404 | size_t numWritten; 405 | 406 | unsigned wideSample; 407 | unsigned sample, channel; 408 | 409 | @try { 410 | // Allocate the MP3 buffer using LAME guide for size 411 | bufferLen = 1.25 * (chunk->mBuffers[0].mNumberChannels * frameCount) + 7200; 412 | buffer = (unsigned char *) calloc(bufferLen, sizeof(unsigned char)); 413 | if (buffer == NULL) { 414 | CACLog(CACDebugLevelError, @"Unable to allocate memory."); 415 | NSError *newError = cac_error(CACMemoryAllocationFailed, nil); 416 | if (error != NULL) *error = newError; 417 | return NO; 418 | } 419 | 420 | // Allocate channel buffers for sample de-interleaving 421 | channelBuffers = calloc(chunk->mBuffers[0].mNumberChannels, sizeof(void *)); 422 | if (channelBuffers == NULL) { 423 | CACLog(CACDebugLevelError, @"Unable to allocate memory."); 424 | NSError *newError = cac_error(CACMemoryAllocationFailed, nil); 425 | if (error != NULL) *error = newError; 426 | return NO; 427 | } 428 | 429 | // Initialize each channel buffer to zero 430 | for(channel = 0; channel < chunk->mBuffers[0].mNumberChannels; ++channel) { 431 | channelBuffers[channel] = NULL; 432 | } 433 | 434 | // Split PCM data into channels and convert to appropriate sample size for LAME 435 | switch(_sourceBitsPerChannel) { 436 | 437 | case 8: 438 | channelBuffers16 = (short **)channelBuffers; 439 | 440 | for(channel = 0; channel < chunk->mBuffers[0].mNumberChannels; ++channel) { 441 | channelBuffers16[channel] = calloc(frameCount, sizeof(short)); 442 | if (channelBuffers16[channel] == NULL) { 443 | 444 | CACLog(CACDebugLevelError, @"Unable to allocate memory."); 445 | NSError *newError = cac_error(CACMemoryAllocationFailed, nil); 446 | if (error != NULL) *error = newError; 447 | return NO; 448 | } 449 | } 450 | 451 | buffer8 = chunk->mBuffers[0].mData; 452 | for(wideSample = sample = 0; wideSample < frameCount; ++wideSample) { 453 | for(channel = 0; channel < chunk->mBuffers[0].mNumberChannels; ++channel, ++sample) { 454 | // Rescale values to short 455 | channelBuffers16[channel][wideSample] = (short)(((buffer8[sample] << 8) & 0xFF00) | (buffer8[sample] & 0xFF)); 456 | } 457 | } 458 | 459 | result = lame_encode_buffer(_gfp, channelBuffers16[0], channelBuffers16[1], frameCount, buffer, bufferLen); 460 | 461 | break; 462 | 463 | case 16: 464 | channelBuffers16 = (short **)channelBuffers; 465 | 466 | for(channel = 0; channel < chunk->mBuffers[0].mNumberChannels; ++channel) { 467 | channelBuffers16[channel] = calloc(frameCount, sizeof(short)); 468 | if (channelBuffers16[channel] == NULL) { 469 | 470 | CACLog(CACDebugLevelError, @"Unable to allocate memory."); 471 | NSError *newError = cac_error(CACMemoryAllocationFailed, nil); 472 | if (error != NULL) *error = newError; 473 | return NO; 474 | } 475 | } 476 | 477 | buffer16 = chunk->mBuffers[0].mData; 478 | for(wideSample = sample = 0; wideSample < frameCount; ++wideSample) { 479 | for(channel = 0; channel < chunk->mBuffers[0].mNumberChannels; ++channel, ++sample) { 480 | channelBuffers16[channel][wideSample] = (short)OSSwapBigToHostInt16(buffer16[sample]); 481 | } 482 | } 483 | 484 | result = lame_encode_buffer(_gfp, channelBuffers16[0], channelBuffers16[1], frameCount, buffer, bufferLen); 485 | 486 | break; 487 | 488 | case 24: 489 | channelBuffers32 = (long **)channelBuffers; 490 | 491 | for(channel = 0; channel < chunk->mBuffers[0].mNumberChannels; ++channel) { 492 | channelBuffers32[channel] = calloc(frameCount, sizeof(long)); 493 | if (channelBuffers32[channel] == NULL) { 494 | 495 | CACLog(CACDebugLevelError, @"Unable to allocate memory."); 496 | NSError *newError = cac_error(CACMemoryAllocationFailed, nil); 497 | if (error != NULL) *error = newError; 498 | return NO; 499 | } 500 | } 501 | 502 | // Packed 24-bit data is 3 bytes, while unpacked is 24 bits in an int32_t 503 | buffer8 = chunk->mBuffers[0].mData; 504 | for(wideSample = sample = 0; wideSample < frameCount; ++wideSample) { 505 | for(channel = 0; channel < chunk->mBuffers[0].mNumberChannels; ++channel) { 506 | // Read three bytes and reconstruct them as a 32-bit BE integer 507 | constructedSample = (int8_t)*buffer8++; constructedSample <<= 8; 508 | constructedSample |= (uint8_t)*buffer8++; constructedSample <<= 8; 509 | constructedSample |= (uint8_t)*buffer8++; 510 | 511 | // Convert to 32-bit sample scaling 512 | channelBuffers32[channel][wideSample] = (long)((constructedSample << 8) | (constructedSample & 0x000000ff)); 513 | } 514 | } 515 | 516 | result = lame_encode_buffer_long2(_gfp, channelBuffers32[0], channelBuffers32[1], frameCount, buffer, bufferLen); 517 | 518 | break; 519 | 520 | case 32: 521 | channelBuffers32 = (long **)channelBuffers; 522 | 523 | for(channel = 0; channel < chunk->mBuffers[0].mNumberChannels; ++channel) { 524 | channelBuffers32[channel] = calloc(frameCount, sizeof(long)); 525 | if (channelBuffers32[channel] == NULL) { 526 | CACLog(CACDebugLevelError, @"Unable to allocate memory."); 527 | NSError *newError = cac_error(CACMemoryAllocationFailed, nil); 528 | if (error != NULL) *error = newError; 529 | return NO; 530 | } 531 | } 532 | 533 | buffer32 = chunk->mBuffers[0].mData; 534 | for(wideSample = sample = 0; wideSample < frameCount; ++wideSample) { 535 | for(channel = 0; channel < chunk->mBuffers[0].mNumberChannels; ++channel, ++sample) { 536 | channelBuffers32[channel][wideSample] = (long)OSSwapBigToHostInt32(buffer32[sample]); 537 | } 538 | } 539 | 540 | result = lame_encode_buffer_long2(_gfp, channelBuffers32[0], channelBuffers32[1], frameCount, buffer, bufferLen); 541 | 542 | break; 543 | 544 | default: 545 | CACLog(CACDebugLevelError, @"Sample size not supported"); 546 | NSString *userInfo = [NSString stringWithFormat:@"File:%@|SampleSize:%u", _secureURLIn.path, (unsigned int)_sourceBitsPerChannel]; 547 | NSError *newError = cac_error(CACUnsupportedSampleSize, userInfo); 548 | if (error != NULL) *error = newError; 549 | return NO; 550 | break; 551 | } 552 | 553 | if (result == -1) { 554 | CACLog(CACDebugLevelError, @"LAME encoding error."); 555 | NSError *newError = cac_error(CACUnknownLAMEError, _secureURLIn.path); 556 | if (error != NULL) *error = newError; 557 | return NO; 558 | } 559 | 560 | numWritten = fwrite(buffer, sizeof(unsigned char), result, _out); 561 | if (result != numWritten) { 562 | CACLog(CACDebugLevelError, @"Unable to write to the output file."); 563 | NSError *newError = cac_error(CACOutputAccessFailed, _secureURLOut.path); 564 | if (error != NULL) *error = newError; 565 | return NO; 566 | } 567 | 568 | return YES; 569 | } 570 | 571 | @finally { 572 | for(channel = 0; channel < chunk->mBuffers[0].mNumberChannels; ++channel) { 573 | free(channelBuffers[channel]); 574 | } 575 | free(channelBuffers); 576 | free(buffer); 577 | } 578 | } 579 | 580 | - (BOOL)finishEncodeWithError:(NSError * __autoreleasing *)error { 581 | 582 | unsigned char *buf; 583 | int bufSize; 584 | 585 | int result; 586 | size_t numWritten; 587 | 588 | @try { 589 | buf = NULL; 590 | 591 | // Allocate the MP3 buffer using LAME guide for size 592 | bufSize = 7200; 593 | buf = (unsigned char *) calloc(bufSize, sizeof(unsigned char)); 594 | if (buf == NULL) { 595 | CACLog(CACDebugLevelError, @"Unable to allocate memory."); 596 | NSError *newError = cac_error(CACMemoryAllocationFailed, nil); 597 | if (error != NULL) *error = newError; 598 | return NO; 599 | } 600 | 601 | // Flush the mp3 buffer 602 | result = lame_encode_flush(_gfp, buf, bufSize); 603 | if (result == -1) { 604 | CACLog(CACDebugLevelError, @"LAME was unable to flush the buffers."); 605 | NSError *newError = cac_error(CACLameBufferFlushFailed, _secureURLIn.path); 606 | if (error != NULL) *error = newError; 607 | return NO; 608 | } 609 | 610 | // And write any frames it returns 611 | numWritten = fwrite(buf, sizeof(unsigned char), result, _out); 612 | if (result != numWritten) { 613 | CACLog(CACDebugLevelError, @"Unable to write to the output file."); 614 | NSError *newError = cac_error(CACOutputAccessFailed, _secureURLOut.path); 615 | if (error != NULL) *error = newError; 616 | return NO; 617 | } 618 | return YES; 619 | } 620 | 621 | @finally { 622 | free(buf); 623 | } 624 | } 625 | 626 | - (BOOL)touchOutputFile:(NSURL *)outputURL { 627 | 628 | NSNumber *permissions = [NSNumber numberWithUnsignedLong:S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH]; 629 | NSDictionary *attributes = [NSDictionary dictionaryWithObject:permissions forKey:NSFilePosixPermissions]; 630 | BOOL result = [[NSFileManager defaultManager] createFileAtPath:outputURL.path 631 | contents:nil 632 | attributes:attributes]; 633 | return result; 634 | } 635 | 636 | #pragma mark - Lazy/Getter 637 | 638 | - (NSFileManager *)fileManager { 639 | return [NSFileManager defaultManager]; 640 | } 641 | 642 | #pragma mark - 643 | @end 644 | -------------------------------------------------------------------------------- /CoreAudioConverter/Encode/MP3EncoderDelegateProtocol.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MP3EncoderDelegateProtocol.h 3 | * CoreAudioConverter 4 | * 5 | * Copyright © 2016 Simon Gaus 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | * 20 | */ 21 | 22 | @import Cocoa; 23 | 24 | NS_ASSUME_NONNULL_BEGIN 25 | 26 | /** 27 | @brief The quality setting for the MP3Encoder. 28 | @discussion This variable is used by lame to select a algorithm. True quality is determined by the bitrate but this variable will effect quality by selecting expensive or cheap algorithms. 29 | */ 30 | typedef NS_ENUM(NSUInteger, LAME_QUALITY) { 31 | 32 | LAME_QUALITY_0 = 0, 33 | LAME_QUALITY_1 = 1, 34 | LAME_QUALITY_2 = 2, 35 | LAME_QUALITY_3 = 3, 36 | LAME_QUALITY_4 = 4, 37 | LAME_QUALITY_5 = 5, 38 | LAME_QUALITY_6 = 6, 39 | LAME_QUALITY_7 = 7, 40 | LAME_QUALITY_8 = 8, 41 | LAME_QUALITY_9 = 9, 42 | /// max. quality, slowest 43 | LAME_QUALITY_MAX = LAME_QUALITY_0, 44 | /// very high quality, slow 45 | LAME_QUALITY_VERY_HIGH = LAME_QUALITY_1, 46 | /// near-best quality, not too slow 47 | LAME_QUALITY_HIGH = LAME_QUALITY_2, 48 | /// good quality, fast 49 | LAME_QUALITY_GOOD = LAME_QUALITY_5, 50 | /// ok quality, really fast 51 | LAME_QUALITY_LOW = LAME_QUALITY_7, 52 | /// min quality, fastest 53 | LAME_QUALITY_MIN = LAME_QUALITY_9 54 | }; 55 | 56 | /** 57 | @brief The constant bitrate we should use to encode the output file. 58 | */ 59 | typedef NS_ENUM(NSUInteger, CONSTANT_BITRATE) { 60 | 61 | CONSTANT_BITRATE_320 = 320, 62 | CONSTANT_BITRATE_256 = 256, 63 | CONSTANT_BITRATE_224 = 224, 64 | CONSTANT_BITRATE_192 = 192, 65 | CONSTANT_BITRATE_160 = 160, 66 | CONSTANT_BITRATE_128 = 128, 67 | CONSTANT_BITRATE_112 = 112, 68 | CONSTANT_BITRATE_96 = 96, 69 | CONSTANT_BITRATE_80 = 80, 70 | CONSTANT_BITRATE_64 = 64, 71 | CONSTANT_BITRATE_56 = 56, 72 | CONSTANT_BITRATE_48 = 48, 73 | CONSTANT_BITRATE_40 = 40, 74 | CONSTANT_BITRATE_32 = 32, 75 | CONSTANT_BITRATE_VERY_HIGH = CONSTANT_BITRATE_320, 76 | CONSTANT_BITRATE_HIGH = CONSTANT_BITRATE_256, 77 | CONSTANT_BITRATE_GOOD = CONSTANT_BITRATE_192, 78 | CONSTANT_BITRATE_OK = CONSTANT_BITRATE_160, 79 | CONSTANT_BITRATE_LOW = CONSTANT_BITRATE_128, 80 | CONSTANT_BITRATE_AUDIOBOOK = CONSTANT_BITRATE_64, 81 | CONSTANT_BITRATE_MIN = CONSTANT_BITRATE_32 82 | }; 83 | 84 | /** 85 | 86 | The delegate of a MP3Encoder object must adopt the MP3EncoderDelegate protocol. 87 | 88 | Required methods of the protocol allow the delegate to decide on the quality and bitrate to use for encoding and to indicate if the encoding should cancel. 89 | 90 | */ 91 | @protocol MP3EncoderDelegate 92 | @required 93 | #pragma mark - Required Methodes 94 | ///---------------------------------------------- 95 | /// @name Required Methodes 96 | ///---------------------------------------------- 97 | 98 | /** 99 | @brief This variable is used by lame to select an algorithm. 100 | @discussion True quality is determined by the bitrate but this variable will effect the quality by selecting expensive or cheap algorithms. 101 | @return The LAME_QUALITY for the MP3Encoder. 102 | */ 103 | - (LAME_QUALITY)quality; 104 | 105 | /** 106 | @brief This variable is used by lame to select the constant bitrate. 107 | @return The CONSTANT_BITRATE the MP3Encoder should use for encoding. 108 | */ 109 | - (CONSTANT_BITRATE)bitrate; 110 | 111 | /** 112 | @brief This variable is used to check if the encoder should cancle the encoding. 113 | @return Yes if the encoding should be stopped, otherwise NO. 114 | */ 115 | - (BOOL)cancel; 116 | 117 | 118 | @end 119 | 120 | NS_ASSUME_NONNULL_END 121 | -------------------------------------------------------------------------------- /CoreAudioConverter/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | de_DE 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 344 23 | NSHumanReadableCopyright 24 | Copyright © 2015-2020 Simon Gaus. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /CoreAudioConverter/Utility/CACDebug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CACDebug.h 3 | * CoreAudioConverter 4 | * 5 | * Copyright © 2015-2020 Simon Gaus 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the Lesser General Public License (LGPL) as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | * 20 | */ 21 | 22 | 23 | @import Foundation; 24 | 25 | NS_ASSUME_NONNULL_BEGIN 26 | 27 | /** 28 | 29 | Define DEBUG_LEVEL if it is not defined in the build settings. 30 | 31 | */ 32 | #ifndef DEBUG_LEVEL 33 | #define DEBUG_LEVEL CACDebugLevelTrace 34 | #endif 35 | 36 | /** 37 | @enum CACDebugLevel 38 | @brief The debug level for a more fine grained control over what is logged. 39 | */ 40 | typedef NS_ENUM(NSUInteger, CACDebugLevel) { 41 | /// Only logs conditions that are fatal and should lead to an exception. 42 | CACDebugLevelFatal = 0, 43 | /// Additionaly logs conditions regarded as an error and wont result in an exception. 44 | CACDebugLevelError = 1, 45 | /// Additionaly logs information that could be helpfull for debugging. 46 | CACDebugLevelInfo = 2, 47 | /// Logs everything. Meant for tracing the flow of the frameworks doings. 48 | CACDebugLevelTrace = 3 49 | }; 50 | 51 | 52 | /** 53 | @brief Prints the given message according to the defined DEBUG_LEVEL and the given debugLevel. 54 | @discussion This funktion will only log the message in DEBUG builds. 55 | @param debugLevel The debug level of the message. 56 | @param format The format string used to printing the format string. 57 | @param ... The arguments for the format sting. 58 | */ 59 | FOUNDATION_EXPORT void CACLog(CACDebugLevel debugLevel, NSString *format, ...) NS_FORMAT_FUNCTION(2,3) NS_NO_TAIL_CALL; 60 | 61 | 62 | NS_ASSUME_NONNULL_END 63 | -------------------------------------------------------------------------------- /CoreAudioConverter/Utility/CircularBuffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CircularBuffer.h 3 | * CoreAudioConverter 4 | * 5 | * Copyright © 2015-2020 Simon Gaus 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the Lesser General Public License (LGPL) as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | * 20 | */ 21 | 22 | @import Foundation; 23 | 24 | /** 25 | 26 | A simple implementation of a circular (AKA ring) buffer. 27 | 28 | */ 29 | 30 | NS_ASSUME_NONNULL_BEGIN 31 | 32 | @interface CircularBuffer : NSObject 33 | #pragma mark - Inititalization 34 | ///------------------------------------------- 35 | /// @name Inititalization 36 | ///------------------------------------------- 37 | 38 | /** 39 | @brief Initializes an CircularBuffer object with a given size. 40 | @param size The size of the buffer. 41 | @return An initialized CircularBuffer object, or nil. 42 | */ 43 | - (nullable instancetype)initWithSize:(NSUInteger)size NS_DESIGNATED_INITIALIZER; 44 | 45 | 46 | #pragma mark - Check available bytes and space 47 | ///-------------------------------------------------------------------- 48 | /// @name Check available bytes and space 49 | ///-------------------------------------------------------------------- 50 | 51 | /** 52 | @brief Returns the number of bytes with valid data in the CircularBuffer. 53 | @discussion Max. value is the size of the CircularBuffer. 54 | @return The number of bytes available. 55 | */ 56 | - (NSUInteger)bytesAvailable; 57 | 58 | /** 59 | @brief Returns the number of bytes that can be written to the buffer before its full. 60 | @return The free space in bytes. 61 | */ 62 | - (NSUInteger)freeSpaceAvailable; 63 | 64 | 65 | #pragma mark - Read data from buffer 66 | ///----------------------------------------------------- 67 | /// @name Read data from buffer 68 | ///----------------------------------------------------- 69 | 70 | /** 71 | @brief This method will copy as many bytes from the CircularBuffer into the buffer as available, with a maximum size specified by byteCount, and return the number of bytes copied to the buffer. 72 | @param buffer The buffer to hold the data that was read from the CircularBuffer. 73 | @param byteCount The size (in bytes) of the data to fetch from the CircularBuffer. 74 | @return The number of bytes copied to the buffer. 75 | */ 76 | - (NSUInteger)getData:(void *)buffer byteCount:(NSUInteger)byteCount; 77 | 78 | 79 | #pragma mark - Write to the buffer 80 | ///------------------------------------------------- 81 | /// @name Write to the buffer 82 | ///------------------------------------------------- 83 | 84 | /** 85 | @brief Returns a buffer 86 | @return Returns a buffer to write to, or nil. 87 | */ 88 | - (nullable void *)exposeBufferForWriting; 89 | 90 | /** 91 | @brief ..... 92 | @param byteCount 93 | @return void 94 | */ 95 | - (void)wroteBytes:(NSUInteger)byteCount; 96 | 97 | 98 | @end 99 | 100 | NS_ASSUME_NONNULL_END 101 | -------------------------------------------------------------------------------- /CoreAudioConverter/Utility/CircularBuffer.m: -------------------------------------------------------------------------------- 1 | /* 2 | * CircularBuffer.m 3 | * CoreAudioConverter 4 | * 5 | * Copyright © 2015-2020 Simon Gaus 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | * 20 | */ 21 | 22 | #import "CircularBuffer.h" 23 | 24 | /* Debug */ 25 | #import "CACDebug.h" 26 | 27 | #pragma mark - CONSTANTS 28 | 29 | // default buffer size 30 | static NSUInteger const BUFFER_INIT_SIZE = 10 * 1024; 31 | 32 | 33 | #pragma mark - CATEGORIES 34 | 35 | 36 | @interface CircularBuffer (/* Private */) 37 | 38 | /// the size of the buffer (buffer end in memory) 39 | @property (nonatomic, readwrite) NSUInteger bufsize; 40 | /// the buffer holding the data (buffer start in memory) 41 | @property (nonatomic, readwrite) uint8_t *buffer; 42 | /// start of valid data 43 | @property (nonatomic, readwrite) uint8_t *readPtr; 44 | /// end of valid data + 1 45 | @property (nonatomic, readwrite) uint8_t *writePtr; 46 | 47 | @end 48 | 49 | 50 | #pragma mark - IMPLEMENTATION 51 | 52 | 53 | @implementation CircularBuffer 54 | #pragma mark - Object creation 55 | 56 | - (nullable instancetype)init { 57 | 58 | // call designated initilaizer 59 | return [self initWithSize:BUFFER_INIT_SIZE]; 60 | } 61 | 62 | - (nullable instancetype)initWithSize:(NSUInteger)size { 63 | 64 | if (size <= 0) return nil; 65 | 66 | self = [super init]; 67 | 68 | if (self) { 69 | 70 | _bufsize = size; 71 | 72 | _buffer = (uint8_t *)calloc(_bufsize, sizeof(uint8_t)); 73 | if (_buffer == NULL) { return nil; } 74 | 75 | _readPtr = _buffer; 76 | _writePtr = _buffer; 77 | } 78 | 79 | return self; 80 | } 81 | 82 | #pragma mark - Methode Implementation 83 | 84 | - (NSUInteger)size { return _bufsize; } 85 | 86 | - (NSUInteger)bytesAvailable { 87 | 88 | return (_writePtr >= _readPtr 89 | ? 90 | // read read 91 | // | | 92 | // v v 93 | //+----------+ +----------+ 94 | //|xxxxxxx | OR | | 95 | //+----------+ +----------+ 96 | // ^ ^ 97 | // | | 98 | // write write 99 | // 100 | (NSUInteger)(_writePtr - _readPtr) 101 | : 102 | // write 103 | // | 104 | // v 105 | //+----------+ 106 | //|x xxx| 107 | //+----------+ 108 | // ^ 109 | // | 110 | // read 111 | // 112 | [self size] - (NSUInteger)(_readPtr - _writePtr)); 113 | } 114 | 115 | - (NSUInteger)freeSpaceAvailable { 116 | 117 | return _bufsize - [self bytesAvailable]; 118 | } 119 | 120 | - (NSUInteger)getData:(void *)buffer byteCount:(NSUInteger)byteCount { 121 | 122 | // forgot to pass a buffer to hold the data ? 123 | if (buffer == NULL) return 0; 124 | 125 | // you want zero bytes you get zero bytes 126 | if(0 == byteCount) { 127 | return 0; 128 | } 129 | 130 | // more bytes are requested than available 131 | if(byteCount > [self bytesAvailable]) { 132 | byteCount = [self bytesAvailable]; 133 | } 134 | // no wrapp needed 135 | if([self contiguousBytesAvailable] >= byteCount) { 136 | memcpy(buffer, _readPtr, byteCount); 137 | _readPtr += byteCount; 138 | } 139 | // buffer needs to wrap 140 | else { 141 | NSUInteger blockSize = [self contiguousBytesAvailable]; 142 | NSUInteger wrapSize = byteCount - blockSize; 143 | 144 | memcpy(buffer, _readPtr, blockSize); 145 | _readPtr = _buffer; 146 | 147 | memcpy(buffer + blockSize, _readPtr, wrapSize); 148 | _readPtr += wrapSize; 149 | } 150 | 151 | return byteCount; 152 | } 153 | 154 | - (void)readBytes:(NSUInteger)byteCount { 155 | uint8_t *limit = _buffer + _bufsize; 156 | 157 | _readPtr += byteCount; 158 | 159 | if(_readPtr > limit) { 160 | _readPtr = _buffer; 161 | } 162 | } 163 | 164 | - (void *)exposeBufferForWriting { 165 | 166 | BOOL erfolg = [self normalizeBuffer]; 167 | if (!erfolg) { 168 | return NULL; 169 | } 170 | return _writePtr; 171 | } 172 | 173 | - (void)wroteBytes:(NSUInteger)byteCount { 174 | uint8_t *limit = _buffer + _bufsize; 175 | 176 | _writePtr += byteCount; 177 | 178 | if(_writePtr > limit) { 179 | _writePtr = _buffer; 180 | } 181 | } 182 | 183 | #pragma mark - Private Methode Implementation 184 | 185 | - (void)dealloc { 186 | free(_buffer); 187 | } 188 | 189 | - (BOOL)normalizeBuffer { 190 | 191 | // reset, nothing to do 192 | if(_writePtr == _readPtr) { 193 | _writePtr = _readPtr = _buffer; 194 | } 195 | // 196 | else if(_writePtr > _readPtr) { 197 | 198 | NSUInteger count = _writePtr - _readPtr; 199 | NSUInteger delta = _readPtr - _buffer; 200 | 201 | memmove(_buffer, _readPtr, count); 202 | 203 | _readPtr = _buffer; 204 | _writePtr -= delta; 205 | } 206 | else { 207 | 208 | NSUInteger chunkASize = [self contiguousBytesAvailable]; 209 | NSUInteger chunkBSize = [self bytesAvailable] - [self contiguousBytesAvailable]; 210 | 211 | uint8_t *chunkA = NULL; 212 | uint8_t *chunkB = NULL; 213 | 214 | chunkA = (uint8_t *)calloc(chunkASize, sizeof(uint8_t)); 215 | //NSAssert1(NULL != chunkA, @"Unable to allocate memory: %s", strerror(errno)); 216 | if (chunkA == NULL) { 217 | CACLog(CACDebugLevelError, @"Unable to allocate memory: %s", strerror(errno)); 218 | return NO; 219 | } 220 | memcpy(chunkA, _readPtr, chunkASize); 221 | 222 | if(0 < chunkBSize) { 223 | chunkB = (uint8_t *)calloc(chunkBSize, sizeof(uint8_t)); 224 | //NSAssert1(NULL != chunkA, @"Unable to allocate memory: %s", strerror(errno)); 225 | if (chunkB == NULL) { 226 | CACLog(CACDebugLevelError, @"Unable to allocate memory: %s", strerror(errno)); 227 | free(chunkA); 228 | return NO; 229 | } 230 | memcpy(chunkB, _buffer, chunkBSize); 231 | } 232 | 233 | memcpy(_buffer, chunkA, chunkASize); 234 | memcpy(_buffer + chunkASize, chunkB, chunkBSize); 235 | 236 | _readPtr = _buffer; 237 | _writePtr = _buffer + chunkASize + chunkBSize; 238 | 239 | // free chunkA & chunkB 240 | free(chunkA); 241 | free(chunkB); 242 | } 243 | 244 | return YES; 245 | } 246 | 247 | - (NSUInteger)contiguousBytesAvailable { 248 | 249 | uint8_t *limit = _buffer + _bufsize; 250 | 251 | 252 | return (_writePtr >= _readPtr 253 | ? 254 | // read read 255 | // | | 256 | // v v 257 | //+----------+ +----------+ 258 | //|xxxxxxx | OR | | 259 | //+----------+ +----------+ 260 | // ^ ^ 261 | // | | 262 | // write write 263 | // 264 | _writePtr - _readPtr 265 | : 266 | // write 267 | // | 268 | // v 269 | //+----------+ 270 | //|x xxx| 271 | //+----------+ 272 | // ^ 273 | // | 274 | // read 275 | // 276 | limit - _readPtr); 277 | } 278 | 279 | - (NSUInteger)contiguousFreeSpaceAvailable { 280 | 281 | uint8_t *limit = _buffer + _bufsize; 282 | return (_writePtr >= _readPtr ? limit - _writePtr : _readPtr - _writePtr); 283 | } 284 | 285 | #pragma mark - 286 | @end 287 | -------------------------------------------------------------------------------- /CoreAudioConverter/de.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* Error description - Returned if an unknown error occurred inside of LAME. */ 2 | "An error occurred inside of LAME, while encoding the file: '%@'." = "In LAME ist beim Codieren der Datei ein Fehler aufgetreten: '%@'."; 3 | 4 | /* Error description - Returned if an unknown error occurred. */ 5 | "An unknown error occurred." = "Ein unbekannter Fehler ist aufgetreten."; 6 | 7 | /* Error description - Returned if an I/O error occurred. */ 8 | "Beim lesen/schreiben ist ein Fehler aufgetreten." = "Beim lesen/schreiben ist ein Fehler aufgetreten."; 9 | 10 | /* Error description - Returned if the decoder for the given file could not be create. */ 11 | "Couldn't create decoder for file: '%@'." = "Der Decoder für die Datei '%@' konnte nicht erstellt werden."; 12 | 13 | /* Error description - Returned if the file type of the input file couldent be detected. */ 14 | "Couldn't detect type for file: '%@', the file may be corrupted." = "Der Dateityp konnte nicht erkannt werden: '%@', die Datei ist möglicherweise beschädigt."; 15 | 16 | /* Error description - Returned if the input file couldent be opened. */ 17 | "Couldn't open the file '%@', the file may be corrupted." = "Die Datei '%@' konnte nicht geöffnet werden, sie ist möglicherweise beschädigt."; 18 | 19 | /* Error description - Returned if a folder was expected and a file was passed. */ 20 | "Das angegebene Objekt ist kein Ordner." = "Das angegebene Objekt ist kein Ordner."; 21 | 22 | /* Error description - Returned if the file system is busy and cannot be removed. */ 23 | "Das Laufwerk ist beschäftigt und kann nicht entfernt werden." = "Das Laufwerk ist beschäftigt und kann nicht entfernt werden."; 24 | 25 | /* Error description - Returned if the volume can't be ejected because it is used by the VM. */ 26 | "Das Laufwerk kann nicht ausgeworfen werden, weil es von der VM benutzt wird." = "Das Laufwerk kann nicht ausgeworfen werden, weil es von der VM benutzt wird."; 27 | 28 | /* Error description - Returned if there is no such volume. */ 29 | "Das Laufwerk konnte nicht gefunden werden." = "Das Laufwerk konnte nicht gefunden werden"; 30 | 31 | /* Error description - Returned if the file/volume is beeing used by another process. */ 32 | "Das Volumen kann nicht ausgeworfen werden, weil es von einem anderen Prozess verwendet wird." = "Das Volumen kann nicht ausgeworfen werden, weil es von einem anderen Prozess verwendet wird."; 33 | 34 | /* Error description - Returned if a bad file name was passed to the routine. */ 35 | "Der Dateiname ist nicht zulässig." = "Der Dateiname ist nicht zulässig."; 36 | 37 | /* Error description - Returned if the selector is not recognized by the filesystem. */ 38 | "Die Aktion wird von dem Dateisystem nicht unterstützt." = "Die Aktion wird von dem Dateisystem nicht unterstützt."; 39 | 40 | /* Error description - Returned if the file or volume is too big for the system. */ 41 | "Die Datei oder Partition ist zu groß." = "Die Datei oder Partition ist zu groß."; 42 | 43 | /* Error description - Returned if the attempted operation is not supported by the filesystem. */ 44 | "Die Operation wird von dem Dateisystem nicht unterstützt." = "Die Operation wird von dem Dateisystem nicht unterstützt."; 45 | 46 | /* Error description - Returned if the operation was canceled by the user. */ 47 | "Die Operation wurde vom Nutzer abgebrochen." = "Die Operation wurde vom Nutzer abgebrochen."; 48 | 49 | /* Error description - Returned if there occurred an unknown Core Foundation error. */ 50 | "Es ist ein unbekannter Fehler im Core Foundation Framework aufgetreten." = "Es ist ein unbekannter Fehler im Core Foundation Framework aufgetreten."; 51 | 52 | /* Error description - Returned if there is no space on the disk. */ 53 | "Es ist kein Platz mehr auf dem Laufwerk." = "Es ist kein Platz mehr auf dem Laufwerk."; 54 | 55 | /* Error description - Returned if there is not enough disk space to perform the requested operation. */ 56 | "Es ist nicht genügend Speicherplatz vorhanden um die Operation auszuführen." = "Es ist nicht genügend Speicherplatz vorhanden um die Operation auszuführen."; 57 | 58 | /* Error description - Returned if the file format is not supported. */ 59 | "File format not supported for file: '%@'" = "Dateiformat für Datei nicht unterstützt: '%@'"; 60 | 61 | /* Error description - Returned if a file has more than 2 channels. */ 62 | "LAME only supports one or two channel input. %@." = "LAME unterstützt nur einen oder zwei Kanal Input. %@."; 63 | 64 | /* Error description - Returned if a file has an unsupported sample size. */ 65 | "LAME only supports sample sizes of 8, 16, 24 and 32. %@." = "LAME unterstützt nur Sampplegrößen von 8, 16, 24 und 32. %@."; 66 | 67 | /* Error description - Returned if LAME was unable to flush the buffer for a file. */ 68 | "LAME was unable to flush the buffers for file: '%@'." = "LAME konnte die Buffer für die Datei '%@' nicht leeren."; 69 | 70 | /* Error description - Returned if the process is not allowed to access the requested file. */ 71 | "The process is not allowed to access the requested file at path '%@'." = "Der Prozess kann unter dem Pfad '%@' nicht auf die angeforderte Datei zugreifen."; 72 | 73 | /* Error description - Returned if there is not enough disc space to encode the file */ 74 | "There is not enough disc space to encode the file at path '%@'." = "Es ist nicht genügend Speicherplatz vorhanden, um die Datei unter dem Pfad '%@' zu codieren."; 75 | 76 | /* Error description - Returned if the output file could not be closed. */ 77 | "Unable to allocate memory." = "Speicher kann nicht zugeordnet werden."; 78 | 79 | /* Error description - Returned if the output file could not be closed. */ 80 | "Unable to close the output file: '%@'." = "Die Ausgabedatei kann nicht geschlossen werden: '%@'."; 81 | 82 | /* Error description - Returned if the lame settings couldent be set. */ 83 | "Unable to initialize the LAME settings. Failed with code: %@" = "Die LAME-Einstellungen können nicht initialisiert werden. Fehlercode: %@"; 84 | 85 | /* Error description - Returned if the output file could not be opened. */ 86 | "Unable to open the output file: '%@'." = "Ausgabedatei kann nicht geöffnet werden: '%@'."; 87 | -------------------------------------------------------------------------------- /CoreAudioConverter/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* Error description - Returned if an unknown error occurred inside of LAME. */ 2 | "An error occurred inside of LAME, while encoding the file: '%@'." = "An error occurred inside of LAME, while encoding the file: '%@'."; 3 | 4 | /* Error description - Returned if an unknown error occurred. */ 5 | "An unknown error occurred." = "An unknown error occurred."; 6 | 7 | /* Error description - Returned if an I/O error occurred. */ 8 | "Beim lesen/schreiben ist ein Fehler aufgetreten." = "An error occurred while reading/writing."; 9 | 10 | /* Error description - Returned if the decoder for the given file could not be create. */ 11 | "Couldn't create decoder for file: '%@'." = "Couldn't create decoder for file: '%@'."; 12 | 13 | /* Error description - Returned if the file type of the input file couldent be detected. */ 14 | "Couldn't detect type for file: '%@', the file may be corrupted." = "Couldn't detect type for file: '%@', the file may be corrupted."; 15 | 16 | /* Error description - Returned if the input file couldent be opened. */ 17 | "Couldn't open the file '%@', the file may be corrupted." = "Couldn't open the file '%@', the file may be corrupted."; 18 | 19 | /* Error description - Returned if a folder was expected and a file was passed. */ 20 | "Das angegebene Objekt ist kein Ordner." = "The specified object is not a folder."; 21 | 22 | /* Error description - Returned if the file system is busy and cannot be removed. */ 23 | "Das Laufwerk ist beschäftigt und kann nicht entfernt werden." = "The drive is busy and cannot be removed."; 24 | 25 | /* Error description - Returned if the volume can't be ejected because it is used by the VM. */ 26 | "Das Laufwerk kann nicht ausgeworfen werden, weil es von der VM benutzt wird." = "The drive cannot be ejected because it is being used by the VM."; 27 | 28 | /* Error description - Returned if there is no such volume. */ 29 | "Das Laufwerk konnte nicht gefunden werden." = "The drive could not be found."; 30 | 31 | /* Error description - Returned if the file/volume is beeing used by another process. */ 32 | "Das Volumen kann nicht ausgeworfen werden, weil es von einem anderen Prozess verwendet wird." = "The volume cannot be ejected because it is being used by another process."; 33 | 34 | /* Error description - Returned if a bad file name was passed to the routine. */ 35 | "Der Dateiname ist nicht zulässig." = "The file name is not allowed."; 36 | 37 | /* Error description - Returned if the selector is not recognized by the filesystem. */ 38 | "Die Aktion wird von dem Dateisystem nicht unterstützt." = "The action is not supported by the file system."; 39 | 40 | /* Error description - Returned if the file or volume is too big for the system. */ 41 | "Die Datei oder Partition ist zu groß." = "The file or partition is too large."; 42 | 43 | /* Error description - Returned if the attempted operation is not supported by the filesystem. */ 44 | "Die Operation wird von dem Dateisystem nicht unterstützt." = "The operation is not supported by the file system."; 45 | 46 | /* Error description - Returned if the operation was canceled by the user. */ 47 | "Die Operation wurde vom Nutzer abgebrochen." = "The operation was canceled by the user."; 48 | 49 | /* Error description - Returned if there occurred an unknown Core Foundation error. */ 50 | "Es ist ein unbekannter Fehler im Core Foundation Framework aufgetreten." = "An unknown error has occurred in the Core Foundation Framework."; 51 | 52 | /* Error description - Returned if there is no space on the disk. */ 53 | "Es ist kein Platz mehr auf dem Laufwerk." = "There is no more space on the drive."; 54 | 55 | /* Error description - Returned if there is not enough disk space to perform the requested operation. */ 56 | "Es ist nicht genügend Speicherplatz vorhanden um die Operation auszuführen." = "There is not enough space to perform the operation."; 57 | 58 | /* Error description - Returned if the file format is not supported. */ 59 | "File format not supported for file: '%@'" = "File format not supported for file: '%@'"; 60 | 61 | /* Error description - Returned if a file has more than 2 channels. */ 62 | "LAME only supports one or two channel input. %@." = "LAME only supports one or two channel input. %@."; 63 | 64 | /* Error description - Returned if a file has an unsupported sample size. */ 65 | "LAME only supports sample sizes of 8, 16, 24 and 32. %@." = "LAME only supports sample sizes of 8, 16, 24 and 32. %@."; 66 | 67 | /* Error description - Returned if LAME was unable to flush the buffer for a file. */ 68 | "LAME was unable to flush the buffers for file: '%@'." = "LAME was unable to flush the buffers for file: '%@'."; 69 | 70 | /* Error description - Returned if the process is not allowed to access the requested file. */ 71 | "The process is not allowed to access the requested file at path '%@'." = "The process is not allowed to access the requested file at path '%@'."; 72 | 73 | /* Error description - Returned if there is not enough disc space to encode the file */ 74 | "There is not enough disc space to encode the file at path '%@'." = "There is not enough disc space to encode the file at path '%@'."; 75 | 76 | /* Error description - Returned if the output file could not be closed. */ 77 | "Unable to allocate memory." = "Unable to allocate memory."; 78 | 79 | /* Error description - Returned if the output file could not be closed. */ 80 | "Unable to close the output file: '%@'." = "Unable to close the output file: '%@'."; 81 | 82 | /* Error description - Returned if the lame settings couldent be set. */ 83 | "Unable to initialize the LAME settings. Failed with code: %@" = "Unable to initialize the LAME settings. Failed with code: %@"; 84 | 85 | /* Error description - Returned if the output file could not be opened. */ 86 | "Unable to open the output file: '%@'." = "Unable to open the output file: '%@'."; 87 | -------------------------------------------------------------------------------- /CoreAudioConverter/fr.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* Error description - Returned if an unknown error occurred. */ 2 | "An unknown error occurred." = "Une erreur inconnue s'est produite."; 3 | 4 | /* Error description - Returned if an I/O error occurred. */ 5 | "Beim lesen/schreiben ist ein Fehler aufgetreten." = "Une erreur s'est produite lors de la lecture / écriture."; 6 | 7 | /* Error description - Returned if a folder was expected and a file was passed. */ 8 | "Das angegebene Objekt ist kein Ordner." = "L'objet spécifié n'est pas un dossier."; 9 | 10 | /* Error description - Returned if the file system is busy and cannot be removed. */ 11 | "Das Laufwerk ist beschäftigt und kann nicht entfernt werden." = "Le lecteur est occupé et ne peut pas être retiré."; 12 | 13 | /* Error description - Returned if the volume can't be ejected because it is used by the VM. */ 14 | "Das Laufwerk kann nicht ausgeworfen werden, weil es von der VM benutzt wird." = "Le lecteur ne peut pas être éjecté car il est utilisé par la machine virtuelle."; 15 | 16 | /* Error description - Returned if there is no such volume. */ 17 | "Das Laufwerk konnte nicht gefunden werden." = "Le lecteur est introuvable."; 18 | 19 | /* Error description - Returned if the file/volume is beeing used by another process. */ 20 | "Das Volumen kann nicht ausgeworfen werden, weil es von einem anderen Prozess verwendet wird." = "Le volume ne peut pas être éjecté car il est utilisé par un autre processus."; 21 | 22 | /* Error description - Returned if a bad file name was passed to the routine. */ 23 | "Der Dateiname ist nicht zulässig." = "Le nom de fichier n'est pas autorisé."; 24 | 25 | /* Error description - Returned if the selector is not recognized by the filesystem. */ 26 | "Die Aktion wird von dem Dateisystem nicht unterstützt." = "L'action n'est pas prise en charge par le système de fichiers."; 27 | 28 | /* Error description - Returned if the file or volume is too big for the system. */ 29 | "Die Datei oder Partition ist zu groß." = "Le fichier ou la partition est trop volumineux."; 30 | 31 | /* Error description - Returned if the attempted operation is not supported by the filesystem. */ 32 | "Die Operation wird von dem Dateisystem nicht unterstützt." = "L'opération n'est pas prise en charge par le système de fichiers."; 33 | 34 | /* Error description - Returned if the operation was canceled by the user. */ 35 | "Die Operation wurde vom Nutzer abgebrochen." = "L'opération a été annulée par l'utilisateur."; 36 | 37 | /* Error description - Returned if there occurred an unknown Core Foundation error. */ 38 | "Es ist ein unbekannter Fehler im Core Foundation Framework aufgetreten." = "Une erreur inconnue s'est produite dans Core Foundation Framework."; 39 | 40 | /* Error description - Returned if there is no space on the disk. */ 41 | "Es ist kein Platz mehr auf dem Laufwerk." = "Il n'y a plus d'espace sur le lecteur."; 42 | 43 | /* Error description - Returned if there is not enough disk space to perform the requested operation. */ 44 | "Es ist nicht genügend Speicherplatz vorhanden um die Operation auszuführen." = "Il n'y a pas assez d'espace pour effectuer l'opération."; 45 | 46 | /* Error description - Returned if the process is not allowed to access the requested file. */ 47 | "The process is not allowed to access the requested file at path '%@'." = "Le processus n'est pas autorisé à accéder au fichier demandé sur le chemin '%@'."; 48 | 49 | /* Error description - Returned if there is not enough disc space to encode the file */ 50 | "There is not enough disc space to encode the file at path '%@'." = "L'espace disque est insuffisant pour encoder le fichier sur le chemin '%@'."; 51 | 52 | /* Error description - Returned if an unknown error occurred inside of LAME. */ 53 | "An error occurred inside of LAME, while encoding the file: '%@'." = "Une erreur s'est produite à l'intérieur de LAME lors de l'encodage du fichier: '%@'."; 54 | 55 | /* Error description - Returned if a file has more than 2 channels. */ 56 | "LAME only supports one or two channel input. %@." = "LAME ne prend en charge qu'une ou deux entrées de canal. %@"; 57 | 58 | /* Error description - Returned if a file has an unsupported sample size. */ 59 | "LAME only supports sample sizes of 8, 16, 24 and 32. %@." = "LAME ne prend en charge que des tailles d'échantillon de 8, 16, 24 et 32. %@"; 60 | 61 | /* Error description - Returned if LAME was unable to flush the buffer for a file. */ 62 | "LAME was unable to flush the buffers for file: '%@'." = "LAME n'a pas pu vider les tampons du fichier: '%@'."; 63 | 64 | /* Error description - Returned if the output file could not be closed. */ 65 | "Unable to allocate memory." = "Impossible d'allouer de la mémoire."; 66 | 67 | /* Error description - Returned if the output file could not be closed. */ 68 | "Unable to close the output file: '%@'." = "Impossible de fermer le fichier de sortie: '%@'."; 69 | 70 | /* Error description - Returned if the lame settings couldent be set. */ 71 | "Unable to initialize the LAME settings. Failed with code: %@" = "Impossible d'initialiser les paramètres LAME. Échec avec le code: %@"; 72 | 73 | /* Error description - Returned if the output file could not be opened. */ 74 | "Unable to open the output file: '%@'." = "Impossible d'ouvrir le fichier de sortie: '%@'."; 75 | 76 | /* Error description - Returned if the decoder for the given file could not be create. */ 77 | "Couldn't create decoder for file: '%@'." = "Impossible de créer le décodeur pour le fichier: '%@'."; 78 | 79 | /* Error description - Returned if the file type of the input file couldent be detected. */ 80 | "Couldn't detect type for file: '%@', the file may be corrupted." = "Impossible de détecter le type du fichier: '%@', le fichier est peut-être corrompu."; 81 | 82 | /* Error description - Returned if the input file couldent be opened. */ 83 | "Couldn't open the file '%@', the file may be corrupted." = "Impossible d'ouvrir le fichier '%@', le fichier est peut-être corrompu."; 84 | 85 | /* Error description - Returned if the file format is not supported. */ 86 | "File format not supported for file: '%@'" = "Format de fichier non pris en charge pour le fichier: '%@'"; 87 | -------------------------------------------------------------------------------- /Integration Test/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Integration Test/MP3EncondingTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // MP3EncondingTests.m 3 | // CoreAudioConverter 4 | // 5 | // Created by Simon Gaus on 28.03.16. 6 | // Copyright © 2016 Simon Gaus. All rights reserved. 7 | // 8 | 9 | @import AVFoundation; 10 | 11 | #import 12 | @import CoreAudioConverter; 13 | 14 | #warning This will use the computers speaker and can possible be very loud or distorted if the encoding failes... 15 | #define TEST_AUDIO YES 16 | #define TEST_AUDIO_EXTENSIVE NO 17 | 18 | @interface MP3EncondingTests : XCTestCase 19 | 20 | @property (nonatomic, strong) NSOperationQueue *opQueue; 21 | @property (nonatomic, strong) NSArray *workload; 22 | @property (nonatomic, readwrite) CONSTANT_BITRATE bitrate; 23 | @property (nonatomic, readwrite) LAME_QUALITY quality; 24 | @property (nonatomic, readwrite) BOOL cancel; 25 | 26 | @end 27 | 28 | @implementation MP3EncondingTests 29 | 30 | 31 | - (void)setUp { 32 | [super setUp]; 33 | // Put setup code here. This method is called before the invocation of each test method in the class. 34 | self.opQueue = [[NSOperationQueue alloc] init]; 35 | [self.opQueue setMaxConcurrentOperationCount:[[NSProcessInfo processInfo] processorCount]]; 36 | [self.opQueue setQualityOfService:NSQualityOfServiceUserInitiated]; 37 | } 38 | 39 | 40 | - (void)tearDown { 41 | // Put teardown code here. This method is called after the invocation of each test method in the class. 42 | NSFileManager *manager = [NSFileManager defaultManager]; 43 | 44 | for (EncoderTask *task in self.workload) { 45 | 46 | if ([manager fileExistsAtPath:[task.tempURL path]]) { 47 | 48 | [manager removeItemAtURL:task.tempURL error:nil]; 49 | } 50 | } 51 | 52 | self.opQueue = nil; 53 | self.bitrate = 0; 54 | self.workload = nil; 55 | 56 | [super tearDown]; 57 | } 58 | 59 | 60 | - (void)testMP3Encoding { 61 | 62 | _cancel = NO; 63 | 64 | // prepare ressources 65 | NSBundle *bundle = [NSBundle bundleForClass:[MP3EncondingTests class]]; 66 | NSString * kfile1Path = [bundle pathForResource:@"Apple Lossless" ofType:@"m4a"]; 67 | NSString * kfile2Path = [bundle pathForResource:@"Apple MPEG-4-Audio (AAC)" ofType:@"m4a"]; 68 | NSString * kfile3Path = [bundle pathForResource:@"AIFF 44100 Hz Stereo 16 Bit" ofType:@"aif"]; 69 | NSString * kfile4Path = [bundle pathForResource:@"AIFF (Linear PCM 24 Bit Big Endian Ganzzahl mit Vorzeichen)" ofType:@"aiff"]; 70 | NSString * kfile5Path = [bundle pathForResource:@"AIFF (Linear PCM 16 Bit Big Endian Ganzzahl mit Vorzeichen)" ofType:@"aiff"]; 71 | NSString * kfile6Path = [bundle pathForResource:@"AIFF (Linear PCM 8 Bit Ganzzahl mit Vorzeichen)" ofType:@"aiff"]; 72 | NSString * kfile7Path = [bundle pathForResource:@"AAC 44.100 Hz Stereo 320 kbits:s" ofType:@"m4a"]; 73 | NSString * kfile8Path = [bundle pathForResource:@"AAC 44.100 Hz Stereo 80 kbits:s (HE)" ofType:@"m4a"]; 74 | NSString * kfile9Path = [bundle pathForResource:@"WAV Microsoft (Signed 16 bit PCM)" ofType:@"wav"]; 75 | 76 | NSString * kfile10Path = [bundle pathForResource:@"wrong_filetype" ofType:@"wma"]; 77 | NSString * kfile11Path = [bundle pathForResource:@"wrong_data" ofType:@"m4a"]; 78 | 79 | 80 | NSArray *pathArray = @[ 81 | kfile1Path, 82 | kfile2Path, 83 | kfile3Path, 84 | kfile4Path, 85 | kfile5Path, 86 | kfile6Path, 87 | kfile7Path, 88 | kfile8Path, 89 | kfile9Path, 90 | kfile10Path, 91 | kfile11Path 92 | ]; 93 | 94 | NSFileManager *manager = [NSFileManager defaultManager]; 95 | 96 | NSMutableArray *muteArray = [NSMutableArray array]; 97 | 98 | NSURL *directoryURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]] isDirectory:YES]; 99 | NSError *tempDirError = nil; 100 | BOOL createdTempDir = [manager createDirectoryAtPath:directoryURL.path 101 | withIntermediateDirectories:YES 102 | attributes:nil 103 | error:&tempDirError]; 104 | if (!createdTempDir) { 105 | if (tempDirError) NSLog(@"%@", tempDirError); 106 | } 107 | 108 | for (int i = 0 ; i < pathArray.count ; i++) { 109 | 110 | 111 | NSURL *tempFileUrl = [directoryURL URLByAppendingPathComponent:[NSString stringWithFormat:@"test-file-out-%d.mp3", i]]; 112 | 113 | EncoderTask *task = [EncoderTask taskWithInputURL:[NSURL fileURLWithPath:pathArray[i]] 114 | outputURL:tempFileUrl 115 | temporaryURL:tempFileUrl]; 116 | 117 | [muteArray addObject:task]; 118 | } 119 | 120 | NSArray *settingsArray = @[ 121 | @{@"bitrate":[NSNumber numberWithInt:CONSTANT_BITRATE_VERY_HIGH], @"quality": [NSNumber numberWithInt:LAME_QUALITY_VERY_HIGH]}, 122 | @{@"bitrate":[NSNumber numberWithInt:CONSTANT_BITRATE_VERY_HIGH], @"quality": [NSNumber numberWithInt:LAME_QUALITY_HIGH]}, 123 | @{@"bitrate":[NSNumber numberWithInt:CONSTANT_BITRATE_VERY_HIGH], @"quality": [NSNumber numberWithInt:LAME_QUALITY_GOOD]}, 124 | @{@"bitrate":[NSNumber numberWithInt:CONSTANT_BITRATE_VERY_HIGH], @"quality": [NSNumber numberWithInt:LAME_QUALITY_LOW]}, 125 | 126 | @{@"bitrate":[NSNumber numberWithInt:CONSTANT_BITRATE_HIGH], @"quality": [NSNumber numberWithInt:LAME_QUALITY_VERY_HIGH]}, 127 | @{@"bitrate":[NSNumber numberWithInt:CONSTANT_BITRATE_HIGH], @"quality": [NSNumber numberWithInt:LAME_QUALITY_HIGH]}, 128 | @{@"bitrate":[NSNumber numberWithInt:CONSTANT_BITRATE_HIGH], @"quality": [NSNumber numberWithInt:LAME_QUALITY_GOOD]}, 129 | @{@"bitrate":[NSNumber numberWithInt:CONSTANT_BITRATE_HIGH], @"quality": [NSNumber numberWithInt:LAME_QUALITY_LOW]}, 130 | 131 | @{@"bitrate":[NSNumber numberWithInt:CONSTANT_BITRATE_GOOD], @"quality": [NSNumber numberWithInt:LAME_QUALITY_VERY_HIGH]}, 132 | @{@"bitrate":[NSNumber numberWithInt:CONSTANT_BITRATE_GOOD], @"quality": [NSNumber numberWithInt:LAME_QUALITY_HIGH]}, 133 | @{@"bitrate":[NSNumber numberWithInt:CONSTANT_BITRATE_GOOD], @"quality": [NSNumber numberWithInt:LAME_QUALITY_GOOD]}, 134 | @{@"bitrate":[NSNumber numberWithInt:CONSTANT_BITRATE_GOOD], @"quality": [NSNumber numberWithInt:LAME_QUALITY_LOW]}, 135 | 136 | @{@"bitrate":[NSNumber numberWithInt:CONSTANT_BITRATE_LOW], @"quality": [NSNumber numberWithInt:LAME_QUALITY_VERY_HIGH]}, 137 | @{@"bitrate":[NSNumber numberWithInt:CONSTANT_BITRATE_LOW], @"quality": [NSNumber numberWithInt:LAME_QUALITY_HIGH]}, 138 | @{@"bitrate":[NSNumber numberWithInt:CONSTANT_BITRATE_LOW], @"quality": [NSNumber numberWithInt:LAME_QUALITY_GOOD]}, 139 | @{@"bitrate":[NSNumber numberWithInt:CONSTANT_BITRATE_LOW], @"quality": [NSNumber numberWithInt:LAME_QUALITY_LOW]} 140 | ]; 141 | 142 | if (!TEST_AUDIO_EXTENSIVE) { 143 | 144 | settingsArray = @[ 145 | @{@"bitrate":[NSNumber numberWithInt:CONSTANT_BITRATE_GOOD], @"quality": [NSNumber numberWithInt:LAME_QUALITY_GOOD]} 146 | ]; 147 | } 148 | 149 | for (NSDictionary *settingsDict in settingsArray) { 150 | 151 | self.bitrate = [(NSNumber *)[settingsDict valueForKey:@"bitrate"] intValue]; 152 | self.quality = [(NSNumber *)[settingsDict valueForKey:@"quality"] intValue]; 153 | self.workload = [muteArray copy]; 154 | 155 | for (EncoderTask *task in self.workload) { 156 | 157 | MP3Encoder *mp3Encoder = [[MP3Encoder alloc] initWithDelegate:self]; 158 | 159 | NSError *encError = nil; 160 | BOOL erfolg = [mp3Encoder executeTask:task 161 | error:&encError]; 162 | if (!erfolg) { 163 | if (encError) NSLog(@"%@", encError); 164 | else NSLog(@"Encoding of file '%@'failed without error.", task.inputURL.lastPathComponent); 165 | } 166 | } 167 | 168 | if (TEST_AUDIO) { 169 | for (EncoderTask *task in self.workload) { 170 | 171 | NSURL* file = task.tempURL; 172 | 173 | if ([manager fileExistsAtPath:file.path]) { 174 | 175 | AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:file error:nil]; 176 | [audioPlayer prepareToPlay]; 177 | [audioPlayer play]; 178 | sleep(4); 179 | [audioPlayer pause]; 180 | } 181 | } 182 | } 183 | 184 | XCTAssertTrue([manager fileExistsAtPath:[self.workload[0] tempURL].path], @"Converting Failed"); 185 | XCTAssertTrue([manager fileExistsAtPath:[self.workload[1] tempURL].path], @"Converting Failed"); 186 | XCTAssertTrue([manager fileExistsAtPath:[self.workload[2] tempURL].path], @"Converting Failed"); 187 | XCTAssertTrue([manager fileExistsAtPath:[self.workload[3] tempURL].path], @"Converting Failed"); 188 | XCTAssertTrue([manager fileExistsAtPath:[self.workload[4] tempURL].path], @"Converting Failed"); 189 | XCTAssertTrue([manager fileExistsAtPath:[self.workload[5] tempURL].path], @"Converting Failed"); 190 | XCTAssertTrue([manager fileExistsAtPath:[self.workload[6] tempURL].path], @"Converting Failed"); 191 | XCTAssertTrue([manager fileExistsAtPath:[self.workload[7] tempURL].path], @"Converting Failed"); 192 | XCTAssertTrue([manager fileExistsAtPath:[self.workload[8] tempURL].path], @"Converting Failed"); 193 | XCTAssertTrue(![manager fileExistsAtPath:[self.workload[9] tempURL].path], @"Converting Failed"); 194 | XCTAssertTrue(![manager fileExistsAtPath:[self.workload[10] tempURL].path], @"Converting Failed"); 195 | } 196 | 197 | } 198 | 199 | - (void)testMP3EncoderInit { 200 | 201 | XCTAssertTrue([[MP3Encoder alloc] initWithDelegate:(NSObject *)[NSObject new]], @"Init Failed"); 202 | } 203 | 204 | 205 | #pragma mark Delegate Methodes 206 | 207 | 208 | - (void)encodingFinished:(NSDictionary *)dict { 209 | 210 | NSLog(@"%@", dict); 211 | } 212 | 213 | 214 | - (void)encodingFinishedwithErrors:(NSArray *)errorArray { 215 | 216 | if (errorArray.count > 0) NSLog(@"%@", errorArray); 217 | } 218 | 219 | 220 | #pragma mark - 221 | @end 222 | -------------------------------------------------------------------------------- /Integration Test/test-files/AAC 44.100 Hz Stereo 320 kbits:s.m4a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files/AAC 44.100 Hz Stereo 320 kbits:s.m4a -------------------------------------------------------------------------------- /Integration Test/test-files/AAC 44.100 Hz Stereo 80 kbits:s (HE).m4a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files/AAC 44.100 Hz Stereo 80 kbits:s (HE).m4a -------------------------------------------------------------------------------- /Integration Test/test-files/AIFF (Linear PCM 16 Bit Big Endian Ganzzahl mit Vorzeichen).aiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files/AIFF (Linear PCM 16 Bit Big Endian Ganzzahl mit Vorzeichen).aiff -------------------------------------------------------------------------------- /Integration Test/test-files/AIFF (Linear PCM 24 Bit Big Endian Ganzzahl mit Vorzeichen).aiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files/AIFF (Linear PCM 24 Bit Big Endian Ganzzahl mit Vorzeichen).aiff -------------------------------------------------------------------------------- /Integration Test/test-files/AIFF (Linear PCM 8 Bit Ganzzahl mit Vorzeichen).aiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files/AIFF (Linear PCM 8 Bit Ganzzahl mit Vorzeichen).aiff -------------------------------------------------------------------------------- /Integration Test/test-files/AIFF 44100 Hz Stereo 16 Bit.aif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files/AIFF 44100 Hz Stereo 16 Bit.aif -------------------------------------------------------------------------------- /Integration Test/test-files/Apple Lossless.m4a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files/Apple Lossless.m4a -------------------------------------------------------------------------------- /Integration Test/test-files/Apple MPEG-4-Audio (AAC).m4a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files/Apple MPEG-4-Audio (AAC).m4a -------------------------------------------------------------------------------- /Integration Test/test-files/WAV Microsoft (Signed 16 bit PCM).wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files/WAV Microsoft (Signed 16 bit PCM).wav -------------------------------------------------------------------------------- /Integration Test/test-files/about.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf460 2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0 5 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0 6 | 7 | \f0\fs24 \cf0 \ 8 | ORIGINAL:\ 9 | Source http://www.freesound.org/people/Blockfighter298/sounds/341327/\ 10 | Type Wave (.wav)\ 11 | Samplerate 44100.0 Hz\ 12 | Bit depth 16 Bit\ 13 | Channels Stereo\ 14 | \ 15 | CONVERTED USING ITUNES:\ 16 | \ 17 | Apple Lossless (.m4a)\ 18 | AIFF 44100 Hz Stereo 16 Bit (.aif)\ 19 | AAC 44.100 Hz Stereo 320 kbits/s (.m4a)\ 20 | AAC 44.100 Hz Stereo 80 kbits/s (HE) (.m4a)\ 21 | \ 22 | \ 23 | CONVERTED USING MAX:\ 24 | \ 25 | AIFF (Linear PCM 16 Bit Big Endian Ganzzahl mit Vorzeichen) .aiff\ 26 | AIFF (Linear PCM 24 Bit Big Endian Ganzzahl mit Vorzeichen) .aiff\ 27 | AIFF (Linear PCM 8 Bit Ganzzahl mit Vorzeichen) .aiff\ 28 | Apple MPEG-4-Audio (AAC) .m4a\ 29 | \ 30 | ITS NOT ABOUT ENCODING QUALITY TESTING} -------------------------------------------------------------------------------- /Integration Test/test-files/test-cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files/test-cover.jpg -------------------------------------------------------------------------------- /Integration Test/test-files/wrong_data.m4a: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf470 2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0 5 | \deftab720 6 | \pard\pardeftab720\partightenfactor0 7 | 8 | \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 9 | Kurzfristig:\ 10 | \'97\'97\'97\'97\'97\'97\'97\'97\'97\'97\'97\'97\'97\ 11 | \ 12 | - Bilder\ 13 | \ 14 | - Kurztext\ 15 | \ 16 | - \'d6ffnungszeiten ?\ 17 | \ 18 | - Kontakt\ 19 | \ 20 | \ 21 | \ 22 | Langfristig:\ 23 | \'97\'97\'97\'97\'97\'97\'97\'97\'97\'97\'97\'97\'97\ 24 | \ 25 | - Leitfaden/Philosophie Text\ 26 | \ 27 | - Praxis Beschreibung\'a0\ 28 | \ 29 | - Praxis/Team- Bilder (Haus-Aussenansicht)\ 30 | \ 31 | - Stellenangebot\ 32 | \ 33 | - Themen/ Was tun wir ?\ 34 | \ 35 | - Auszeichnungen/Verb\'e4nde\ 36 | \ 37 | - Preisliste} -------------------------------------------------------------------------------- /Integration Test/test-files/wrong_filetype.wma: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf470 2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0 5 | \deftab720 6 | \pard\pardeftab720\partightenfactor0 7 | 8 | \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 9 | Kurzfristig:\ 10 | \'97\'97\'97\'97\'97\'97\'97\'97\'97\'97\'97\'97\'97\ 11 | \ 12 | - Bilder\ 13 | \ 14 | - Kurztext\ 15 | \ 16 | - \'d6ffnungszeiten ?\ 17 | \ 18 | - Kontakt\ 19 | \ 20 | \ 21 | \ 22 | Langfristig:\ 23 | \'97\'97\'97\'97\'97\'97\'97\'97\'97\'97\'97\'97\'97\ 24 | \ 25 | - Leitfaden/Philosophie Text\ 26 | \ 27 | - Praxis Beschreibung\'a0\ 28 | \ 29 | - Praxis/Team- Bilder (Haus-Aussenansicht)\ 30 | \ 31 | - Stellenangebot\ 32 | \ 33 | - Themen/ Was tun wir ?\ 34 | \ 35 | - Auszeichnungen/Verb\'e4nde\ 36 | \ 37 | - Preisliste} -------------------------------------------------------------------------------- /Integration Test/test-files_backup/AAC 44.100 Hz Stereo 320 kbits:s.m4a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files_backup/AAC 44.100 Hz Stereo 320 kbits:s.m4a -------------------------------------------------------------------------------- /Integration Test/test-files_backup/AAC 44.100 Hz Stereo 80 kbits:s (HE).m4a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files_backup/AAC 44.100 Hz Stereo 80 kbits:s (HE).m4a -------------------------------------------------------------------------------- /Integration Test/test-files_backup/AIFF (Linear PCM 16 Bit Big Endian Ganzzahl mit Vorzeichen).aiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files_backup/AIFF (Linear PCM 16 Bit Big Endian Ganzzahl mit Vorzeichen).aiff -------------------------------------------------------------------------------- /Integration Test/test-files_backup/AIFF (Linear PCM 24 Bit Big Endian Ganzzahl mit Vorzeichen).aiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files_backup/AIFF (Linear PCM 24 Bit Big Endian Ganzzahl mit Vorzeichen).aiff -------------------------------------------------------------------------------- /Integration Test/test-files_backup/AIFF (Linear PCM 8 Bit Ganzzahl mit Vorzeichen).aiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files_backup/AIFF (Linear PCM 8 Bit Ganzzahl mit Vorzeichen).aiff -------------------------------------------------------------------------------- /Integration Test/test-files_backup/AIFF 44100 Hz Stereo 16 Bit.aif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files_backup/AIFF 44100 Hz Stereo 16 Bit.aif -------------------------------------------------------------------------------- /Integration Test/test-files_backup/Apple Lossless.m4a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files_backup/Apple Lossless.m4a -------------------------------------------------------------------------------- /Integration Test/test-files_backup/Apple MPEG-4-Audio (AAC).m4a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files_backup/Apple MPEG-4-Audio (AAC).m4a -------------------------------------------------------------------------------- /Integration Test/test-files_backup/about.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf460 2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0 5 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0 6 | 7 | \f0\fs24 \cf0 \ 8 | ORIGINAL:\ 9 | Source http://www.freesound.org/people/Blockfighter298/sounds/341327/\ 10 | Type Wave (.wav)\ 11 | Samplerate 44100.0 Hz\ 12 | Bit depth 16 Bit\ 13 | Channels Stereo\ 14 | \ 15 | CONVERTED USING ITUNES:\ 16 | \ 17 | Apple Lossless (.m4a)\ 18 | AIFF 44100 Hz Stereo 16 Bit (.aif)\ 19 | AAC 44.100 Hz Stereo 320 kbits/s (.m4a)\ 20 | AAC 44.100 Hz Stereo 80 kbits/s (HE) (.m4a)\ 21 | \ 22 | \ 23 | CONVERTED USING MAX:\ 24 | \ 25 | AIFF (Linear PCM 16 Bit Big Endian Ganzzahl mit Vorzeichen) .aiff\ 26 | AIFF (Linear PCM 24 Bit Big Endian Ganzzahl mit Vorzeichen) .aiff\ 27 | AIFF (Linear PCM 8 Bit Ganzzahl mit Vorzeichen) .aiff\ 28 | Apple MPEG-4-Audio (AAC) .m4a\ 29 | \ 30 | ITS NOT ABOUT ENCODING QUALITY TESTING} -------------------------------------------------------------------------------- /Integration Test/test-files_backup/test-cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/Integration Test/test-files_backup/test-cover.jpg -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /OptimizationProfiles/CoreAudioConverter.profdata: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phisto/CoreAudioConverter/56e3888becb2ce6dd4f7beeb4eeedc742ccbd127/OptimizationProfiles/CoreAudioConverter.profdata -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 2 | [![License](https://img.shields.io/github/license/phisto/CoreAudioConverter.svg)](https://github.com/Phisto/CoreAudioConverter) 3 | 4 | # CoreAudioConverter 5 | 6 | ## Overview 7 | 8 | The CoreAudioConverter framework provides facilities for converting various audio file formats to MPEG Audio Layer III, 9 | more commonly referred to as MP3. 10 | 11 | ## Supported Audio Formats 12 | 13 | - Audio Interchange File Format (AIFF) 14 | - Apple Lossless Audio Codec (ALAC) 15 | - Advanced Audio Coding (ACC) 16 | 17 | ## Requirements 18 | 19 | - macOS 10.10+ 20 | - Xcode 10.1+ 21 | 22 | ## Installation 23 | 24 | ### Carthage 25 | 26 | [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. To integrate CoreAudioConverter into your Xcode project using Carthage, specify it in your `Cartfile`: 27 | 28 | ```ogdl 29 | github "Phisto/CoreAudioConverter" ~> 1.0 30 | ``` 31 | 32 | ### Manually 33 | 34 | If you prefer not to use Carthage, you can integrate CoreAudioConverter into your project manually. 35 | You only need to build and add the CoreAudioConverter framework (CoreAudioConverter.framework) to your project. 36 | 37 | ## Usage 38 | 39 | ```objectivec 40 | 41 | // create the encoder task 42 | NSURL *fileURL = <#...#> 43 | NSURL *outFileUrl = <#...#> 44 | EncoderTask *task = [EncoderTask taskWithInputURL:fileURL 45 | outputURL:outFileUrl 46 | temporaryURL:nil]; 47 | 48 | // create the encoder 49 | MP3Encoder *mp3Encoder = [[MP3Encoder alloc] initWithDelegate:self]; 50 | if (!mp3Encoder) { 51 | <#// handle failure...#> 52 | } 53 | 54 | NSError *encodingError = nil; 55 | BOOL erfolg = [mp3Encoder executeTask:task error:&encodingError]; 56 | if (!erfolg) { 57 | <#// handle failure...#> 58 | } 59 | 60 | ``` 61 | 62 | ## LAME 63 | 64 | The CoreAudioConverter framework is using [LAME](http://lame.sourceforge.net/) to encode files to MP3. 65 | *LAME is a high quality MPEG Audio Layer III encoder licensed under the [GNU Lesser General Public License (LGPL)](https://www.gnu.org/licenses/).* 66 | 67 | ## Audio File Tagger 68 | 69 | The CoreAudioConverter framework is using the [AudioFileTagger](https://github.com/Phisto/AudioFileTagger) framework to tag the encoded MP3 files with ID3v2 tags. 70 | *AudioFileTagger is released under the [GNU Lesser General Public License (LGPL)](https://www.gnu.org/licenses/).* 71 | 72 | ## Credits 73 | 74 | I learned a lot by browsing trough the [code repository](https://github.com/sbooth/Max) for the brilliant macOS application [Max](https://sbooth.org/Max/). 75 | 76 | ## License 77 | 78 | CoreAudioConverter is released under the [GNU Lesser General Public License (LGPL)](https://www.gnu.org/licenses/). 79 | --------------------------------------------------------------------------------