rebol [ title: "MP3 related functions" author: "oldes" ] mp3: make object! [ header: ;frame header (binary!) frame: none ;mp3 frame (binary!) sdsize: 0 ;parsed frameHeader variables: Syncword: MpegVersion: Layer: ProtectionBit: Bitrate: SamplingRate: PaddingBit: reserved: ChannelMode: ModeExtension: Copyright: Original: Emphasis: none ;---------------------- getMp3Frame: func[port][ frame: none if not none? header: copy/part port 4 [ if 255 <> first header [ print ["ID3?" mold header] switch (to-string copy/part header 3) [ "ID3" [ print "ID3" append header copy/part port 6 id3: copy/part port third parse-ID3header header probe length? id3 ] "TAG" [ copy/part port 124 ] ] header: copy/part port 4 ] if not none? header [ parse-Mp3FrameHeader header frame: copy/part port to-integer sdsize ] ] frame ] SynchsafeInt: func[bin [binary!] "4 bytes"][ to integer! debase/base ( join "000" head remove skip (remove skip (remove skip (enbase/base bin 2) 8) 7) 7 ) 2 ] parse-ID3header: func[header [binary!] /local version flags size][ set [version flags tmp] next slice-bin header [3 2 1 4] flags: enbase/base flags 2 size: (SynchsafeInt tmp) + either flags/2 = "1" [10][0] reduce [version flags size] ] parse-Mp3FrameHeader: func[header [binary!]][ ;probe header set [ Syncword MpegVersion Layer ProtectionBit Bitrate SamplingRate PaddingBit Reserved ChannelMode ModeExtension Copyright Original Emphasis ] slice-bin/integers (enbase/base header 2) [11 2 2 1 4 2 1 1 2 2 1 1 2] ;print ["MpegVersion:" MpegVersion] Bitrate: pick (switch layer either MpegVersion = 3 [[ 3 [[32 64 96 128 160 192 224 256 288 320 352 384 416 448]] 2 [[32 48 56 64 80 96 112 128 160 192 224 256 320 384]] 1 [[32 40 48 56 64 80 96 112 128 160 192 224 256 320]] ]][[ 3 [[32 48 56 64 80 96 112 128 144 160 176 192 224 256]] 2 [[ 8 16 24 32 40 48 56 64 80 96 112 128 144 160]] 1 [[ 8 16 24 32 40 48 56 64 80 96 112 128 144 160]] ]]) Bitrate SamplingRate: pick switch MpegVersion [ 3 [[44100 48000 32000 "--"]] 2 [[22050 24000 16000 "--"]] 0 [[11025 12000 8000 "--"]] ] (1 + SamplingRate) ;sdsize: to-integer ((((either MpegVersion = 3 [144][72]) * Bitrate * 1000) / SamplingRate) + PaddingBit - 4) ;comment { sdsize: either MpegVersion = 3 [ ;version 1 ((( either layer = 3 [48000][144000]) * bitrate) / SamplingRate) + PaddingBit - 4 ][ ((( either layer = 3 [24000][72000]) * bitrate) / SamplingRate) + PaddingBit - 4 ] ;} comment { print [tabs "MpegVersion:" pick [2.5 "" 2 1] (1 + MpegVersion) "Layer:" pick ["" "III" "II" "I"] (1 + Layer) "Protected by CRC:" ProtectionBit = 1 ] print [tabs "Bitrate:" Bitrate "SamplingRate:" SamplingRate "PaddingBit:" PaddingBit = 1 ] print [tabs "ChannelMode:" pick ["Stereo" "Joint stereo (Stereo)" "Dual channel" "Single channel (Mono)"] (1 + ChannelMode) "Copyright:" Copyright = 1 "Original:" Original = 1 "Emphasis:" pick [none "50/15 ms" "" "CCIT J.17"] (1 + Emphasis) ] print [tabs "SampleDataSize:" sdsize] ;probe sdsize: to-integer ((((either MpegVersion = 3 [144][72]) * Bitrate * 1000) / SamplingRate) + PaddingBit - 4) } ] ] ;m: open/direct/binary %/j/test/track03.mp3 %/j/binladin.mp3 ; ;getMp3Frame m ;getMp3Frame m ;close m ;----------------------------------wav functions----------------------------- wav: make object! [ WORD: [copy v 2 skip (v: to integer! to binary! head reverse v)] DWORD: [copy v 4 skip (v: to integer! to binary! head reverse v)] RIFF-CHUNK: [ copy id 4 skip ;identifier, e.g. "fmt " or "data" DWORD ;remaining chunk length after header copy chunk-data v skip ( (print [id v]) switch id [ "fmt " [parse/all chunk-data RIFF-FMT-CHUNK] "data" [data-ck: to binary! chunk-data] ] ) ] RIFF-FMT-CHUNK: [ WORD (fmt-ck/wFormatTag: v) WORD (fmt-ck/wChannels: v) DWORD (fmt-ck/dwSamplesPerSec: v) DWORD (fmt-ck/dwAvgBytesPerSec: v) WORD (fmt-ck/wBlockAlign: v) ] id: riff-data: none chunk-data: none data-ck: none fmt-ck: make object! [ wFormatTag: ;Format category wChannels: ;Number of channels dwSamplesPerSec: ;Sampling rate dwAvgBytesPerSec: ;For buffer estimation wBlockAlign: ;Data block size 0 ] parse-wav: func[bin][ data-ck: none parse/all bin [ "RIFF" ;identifier string DWORD ;remaining length after this header copy riff-data v skip ( parse/all riff-data [ copy riff-id 4 skip any [RIFF-CHUNK] ] ) ] ] ]