Make Playstation3 play AAC files

Odd machine, this Sony Playstation3. The processing powerhouse plays DIVX movies, WMA9 audio, and AVCHD movies with AAC packed in MP4 part 14 containers (*). M4v that is. But doesn't support the open standard MP4 audio (M4a) that most audio players (including Walkman® killer iPod) use today. Instead genious Sony supports AAC in 3gpp containers, used in GSM mobile phones. Well it's not really a proprietary format, which Sony is very well disrespected for embracing, but more an annoyance to Apple I guess (and of course Playstation owners). See the actual audio track of and M4a file is identical to the 3gpp file. Both are compressed using  AAC. Only the container and the tags (i.e. album, artist etc.) are different, so it's easy and lossless to convert one format to the other -  no transcoding necessary. The following Powershell 2.0 script converts an M4A file to 3gpp, preserving the tagging in the file. Two dependencies are requred: Mp4Box and AtomicParsley. Drop the binaries with the script. The one parameter the .ps1 script needs is the input mp4 audio file.

Param ($m4aFile = "sample.m4a")  
$regex = [regex]'(?x)Atom[^\w]+(?<key>\w+)[^:]+:\s(?<value>.+)'
$tags = @{ }
.\AtomicParsley ($m4aFile) -t |
    foreach {$regex.matches($_)} |
        foreach {
            if (!$tags.Contains($_.Groups["key"].Value)) {
                $tags.Add($_.Groups["key"].Value, $_.Groups["value"].Value)
                }
            }
$newFile = [System.IO.Path]::ChangeExtension($m4aFile, ".3gp")
$newFile
$map = @{
    "nam" = "--3gp-title";
    "wrt" = "--3gp-author";
    "ART" = "--3gp-performer";
    "gnre" = "--3gp-genre";
    "desc" = "--3gp-description";
    "cprt" = "--3gp-copyright";
    "alb" = "--3gp-album";
    "day" = "--3gp-year";
    "keyword" = "--3gp-keyword";
}
[void] (.\MP4Box ($m4aFile) -out ($newFile) -brand 3gp6 -3gp -isma -psp -new)
$a = @($newFile, "-W")
$tags.Keys | foreach {
    if ($_ -ne $null -and $map.Contains($_))
    {
        $a += $map[$_]
        $a += $tags[$_]
        if ($_ -eq "alb" -and $tags.Contains("trkn"))
        {
            $a += "track=" + $tags["trkn"]
        }
        if ($_ -ne "day")
        {
            $a += "UTF16"
        }
    }
}
[void] (.\AtomicParsley @a)

For your convenience here's an archive with script, dependencies and a sample file.

Google
m@kli.dk @klinkby RSS feed  GitHub