Obtain infos from different audio file formats

Mac OSX specific forum
User avatar
Shardik
Addict
Addict
Posts: 2076
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Obtain infos from different audio file formats

Post by Shardik »

The following code example uses the AudioToolBox framework to examine audio files of different formats and to display infos contained in those files. For example when examining the downloaded iTunes file "Song of the Lonely Mountain (Extended Version).m4a" the following info will be displayed:
Audio file info wrote:album: The Hobbit: An Unexpected Journey (Original Motion Picture Soundtrack)
composer: Neil Finn
genre: Soundtrack
year: 2012-12-07T08:00:00Z
comments: (Extended Version)
artist: Neil Finn
approximate duration in seconds: 361.056
copyright:
track number: 12/17
title: Song of the Lonely Mountain (Extended Version)
For my mp3 file "Shakira _ Rabiosa.mp3" the following information is displayed:
Audio file info wrote:title: Shakira / Rabiosa
album: Intro
approximate duration in seconds: 203.416
track number: 10
genre: Unbekannt
artist: Lucenzo
The displayed information may vary depending on the file type and may also vary depending on the MacOS version. The above information for the .m4a file was displayed on Mountain Lion. On Snow Leopard only the approximate duration was displayed. It seems that Apple has further improved the scanning ability of the AudioToolBox functions for m4a files in Mountain Lion... :wink:

In a first version I used some CocoaMessage() API functions, for example to create an AudioFileURL, but I decided to replace all CocoaMessage() API functions by Core Foundation (CF) functions because the CoreAudio and AudioToolBox frameworks are programmed in C and not in Objective C and as a big advantage the example code now runs without any changes with the default Cocoa framework (x86 and x64, in ASCII and Unicode mode) and the subsystem Carbon (x86, in ASCII and Unicode mode).

Code: Select all

; http://www.purebasic.fr/english/viewtopic.php?f=19&t=54607&start=0
; Shardik

EnableExplicit

#AudioFile = "/Users/Shardik/Music/iTunes/iTunes Media/Music/Howard Shore/The Hobbit_ An Unexpected Journey (Original Motion Picture Soundtrack)/2-12 Song of the Lonely Mountain (Extended Version).m4a"
; #AudioFile = "/Volumes/Daten/Musik/Chart Attack Autumn '11/10-Shakira _ Rabiosa.mp3"

#kAudioFilePropertyInfoDictionary = $696E666F ; 'info'
#kAudioFileReadPermission = 1
#kCFURLPOSIXPathStyle = 0

ImportC "/System/Library/Frameworks/AudioToolBox.framework/AudioToolBox"
  AudioFileClose(AudioFileID.I)
  AudioFileGetProperty(AudioFileID.I, PropertyID.L, *DataSize, *PropertyData)
  AudioFileGetPropertyInfo(AudioFileID.I, PropertyID.L, *DataSize, *IsWritable)
  AudioFileOpenURL(FileURLRef.I, Permissions.B, FileTypeHint.I, *AudioFileID)
EndImport

ImportC ""
  CFDictionaryGetCount(DictionaryRef.L)
  CFDictionaryGetKeysAndValues(DictionaryRef.L, *Keys, *Values)
  CFRelease(CFType.I)
  CFStringGetCString(CFStringRef.I, *StringBuffer, BufferSize.I, CFStringEncoding.L)
  CFURLCreateWithFileSystemPath(AllocatorRef.I, CFStringFilePath.I, PathStyle.I, IsDirectory.I)
EndImport

Procedure.S ConvertCFStringIntoString(CFStringRef.I)
  Protected String.S = Space(256)

  CFStringGetCString(CFStringRef, @String, Len(String), 0)

  CompilerIf #PB_Compiler_Unicode
    PokeS(@String, PeekS(@String, -1, #PB_Ascii), -1, #PB_Unicode)
  CompilerEndIf
  ProcedureReturn Trim(String)
EndProcedure

Define *AudioFileBuffer
Define AudioFileRef.I
Define AudioFileID.I
Define AudioFileURL.I
Define DictionaryRef.I
Define DictionarySize.L
Define i.I
Define KeyCount.I

If FileSize(#AudioFile) = -1
  MessageRequester("Error", "The Audio file" + #CR$ + #CR$ + GetFilePart(#AudioFile) + #CR$ + #CR$ + "in the path" + #CR$ + #CR$ + GetPathPart(#AudioFile) + #CR$ + #CR$ + "cannot be found!")
  End
EndIf

*AudioFileBuffer = AllocateMemory(StringByteLength(#AudioFile, #PB_Ascii))
PokeS(*AudioFileBuffer, #AudioFile, MemorySize(*AudioFileBuffer), #PB_Ascii)
AudioFileRef = CFStringCreateWithCString_(0, *AudioFileBuffer, 0)
FreeMemory(*AudioFileBuffer)

If AudioFileRef
  AudioFileURL = CFURLCreateWithFileSystemPath(0, AudioFileRef, #kCFURLPOSIXPathStyle, #False)
  
  If AudioFileURL
    If AudioFileOpenURL(AudioFileURL, #kAudioFileReadPermission, 0, @AudioFileID) = 0
      If AudioFileGetPropertyInfo(AudioFileID, #kAudioFilePropertyInfoDictionary, @DictionarySize, #False) = 0
        If AudioFileGetProperty(AudioFileID, #kAudioFilePropertyInfoDictionary, @DictionarySize, @DictionaryRef) = 0
          KeyCount = CFDictionaryGetCount(DictionaryRef)
          
          If KeyCount > 0
            Dim Key(KeyCount - 1)
            Dim Value(KeyCount - 1)
            CFDictionaryGetKeysAndValues(DictionaryRef, @Key(0), @Value(0))
            
            For i = 0 To KeyCount - 1
              Debug ConvertCFStringIntoString(Key(i)) + ": " + ConvertCFStringIntoString(Value(i))
            Next i
          EndIf
          
          CFRelease(DictionaryRef)
        EndIf
      EndIf
      
      AudioFileClose(AudioFileID)
    EndIf
  EndIf

  CFRelease(AudioFileRef)
EndIf