ApplicationModel.st
author martin
Tue, 07 Nov 2000 15:33:17 +0100
changeset 1418 d2fb63f4a457
parent 1417 810fdd94d742
child 1419 3733848df42c
permissions -rw-r--r--
Structuring categories.

"{ Package: '__NoProject__' }"

"{ NameSpace: SaugFix }"

ApplicationModel subclass:#MP3FileHeader
	instanceVariableNames:'long filesize'
	classVariableNames:''
	poolDictionaries:''
	category:'Description'
!


!MP3FileHeader class methodsFor:'instance creation'!

from: aFilename

     ^ super new filename: aFilename
! !

!MP3FileHeader methodsFor:'accessing'!

bitrate

    "/ Original table from a MP3 documentation:
    "/
    "/    Bit 16   Bit 17   Bit 18   Bit 19   Dezimal   MPEG 1       MPEG 1       MPEG 1       MPEG 2       MPEG 2       MPEG 2
    "/                                                  Layer I      Layer II     Layer III    Layer I      Layer II     Layer III
    "/    0        0        0        0        0         -            -            -            -            -            -
    "/    0        0        0        1        1          32 kBit/s    32 kBit/s    32 kBit/s    32 kBit/s    32 kBit/s     8 kBit/s
    "/    0        0        1        0        2          64 kBit/s    48 kBit/s    40 kBit/s    64 kBit/s    48 kBit/s    16 kBit/s
    "/    0        0        1        1        3          96 kBit/s    56 kBit/s    48 kBit/s    96 kBit/s    56 kBit/s    24 kBit/s
    "/    0        1        0        0        4         128 kBit/s    64 kBit/s    56 kBit/s   128 kBit/s    64 kBit/s    32 kBit/s
    "/    0        1        0        1        5         160 kBit/s    80 kBit/s    64 kBit/s   160 kBit/s    80 kBit/s    64 kBit/s
    "/    0        1        1        0        6         192 kBit/s    96 kBit/s    80 kBit/s   192 kBit/s    96 kBit/s    80 kBit/s
    "/    0        1        1        1        7         224 kBit/s   112 kBit/s    96 kBit/s   224 kBit/s   112 kBit/s    56 kBit/s
    "/    1        0        0        0        8         256 kBit/s   128 kBit/s   112 kBit/s   256 kBit/s   128 kBit/s    64 kBit/s
    "/    1        0        0        1        9         288 kBit/s   160 kBit/s   128 kBit/s   288 kBit/s   160 kBit/s   128 kBit/s
    "/    1        0        1        0       10         320 kBit/s   192 kBit/s   160 kBit/s   320 kBit/s   192 kBit/s   160 kBit/s
    "/    1        0        1        1       11         352 kBit/s   224 kBit/s   192 kBit/s   352 kBit/s   224 kBit/s   112 kBit/s
    "/    1        1        0        0       12         384 kBit/s   256 kBit/s   224 kBit/s   384 kBit/s   256 kBit/s   128 kBit/s
    "/    1        1        0        1       13         416 kBit/s   320 kBit/s   256 kBit/s   416 kBit/s   320 kBit/s   256 kBit/s
    "/    1        1        1        0       14         448 kBit/s   384 kBit/s   320 kBit/s   448 kBit/s   384 kBit/s   320 kBit/s
    "/    1        1        1        1       15         -            -            -            -            -            -

    | index |
    index := 1 + ( ( long copy bitAnd: 2r00000000000000001111000000000000 ) >> ( 32 - 20 ) ).
    index := index   +   ( 16 * ( self layer - 1 ) )   +   ( 48 * ( self version - 1) ).

    ^ #( nil  32  64  96 128 160 192 224 256 288 320 352 384 416 448  nil 
         nil  32  48  56  64  80  96 112 128 160 192 224 256 320 384  nil 
         nil  32  40  48  56  64  80  96 112 128 160 192 224 256 320  nil 
         nil  32  64  96 128 160 192 224 256 288 320 352 384 416 448  nil
         nil  32  48  56  64  80  96 112 128 160 192 224 256 320 348  nil 
         nil   8  16  24  32  64  80  56  64 128 160 112 128 256 320  nil ) at: index.
!

copyright

    ^ ( long bitAt: ( 32 - 28 ) ) == 1.
!

filename: aFilename

    | stream start |
    stream := aFilename readStream.

    start  := stream peek.

    "Is there a sync?"
    start = 255 asCharacter ifFalse: [   "Seems to have an MP3V2 ID3 Information at file beginning."
        stream skipFor: 255 asCharacter. "We take next sync point. Best we could do."
        stream backStep.
        stream backStep.
    ].

    long := stream nextLong.

    filesize := stream size.

    stream close.

"/    Transcript
"/        cr;
"/        showCr: aFilename asString;
"/        cr;
"/        showCr: 'header:           ', ( ( long printStringBase: 2 ) leftPaddedTo: 32 with: $0 );
"/        showCr: 'Size:             ', filesize               printString;
"/        showCr: 'Version:          ', self version           printString;
"/        showCr: 'Layer:            ', self layer             printString;
"/        showCr: 'Protection:       ', self protection        printString;
"/        showCr: 'Bitrate:          ', self bitrate           printString;
"/        showCr: 'Sample frequnecy: ', self samplingFrequency printString;
"/        showCr: 'Padding:          ', self padding           printString;
"/        showCr: 'Private:          ', self private           printString;
"/        showCr: 'Mode:             ', self mode              printString;
"/        showCr: 'Copyright:        ', self copyright         printString;
"/        showCr: 'Original home:    ', self originalHome      printString;
"/        showCr: 'Length:           ', self length            printString.
!

layer

    "/ Original table from a MP3 documentation:
    "/
    "/    Bit 13    Bit 14    Dezimal   Layer
    "/    0         0         0         undef.
    "/    0         1         1         Layer III
    "/    1         0         2         Layer II
    "/    1         1         3         Layer I

    | index |
    index := ( long copy bitAnd: 2r00000000000001100000000000000000 ) >> ( 32 - 15 ).

    ( index == 0 ) ifTrue: [ ^ nil ].

    ^ 4 - index.
!

length

    "Not in the header, but we're able to calculate it. ;-)"
    "Calculation is not absolute precise, because instead of filesize we should"
    "calculate with the size of the used data without any headers and ID3-tags."
    "The lack of precision is about one second."

    | time |
    time := Time fromSeconds: ( 8 * filesize / ( self bitrate * 1000 ) ) asInteger.

    ^ ( ( time minutes printString ) leftPaddedTo: 2 with: $ ) , ':', ( ( time seconds printString ) paddedTo:2 with: $0 ).
!

mode

    "/ Original table from a MP3 documentation:
    "/
    "/    Bit 24  Bit 25  Dezimal  Mode
    "/    0       0       0        Stereo
    "/    0       1       1        Joint-Stereo
    "/    1       0       2        Dual-Channel
    "/    1       1       3        Mono

    | index |
    index := 1 + ( ( long copy bitAnd: 2r00000000000000000000000011000000 ) >> ( 32 - 26 ) ).

    ^ #( #Stereo #'Joint-Stereo' #'Dual-Channel' #Mono ) at: index.
!

originalHome

    ^ ( long bitAt: ( 32 - 29 ) ) == 1.
!

padding

    ^ ( long bitAt: ( 32 - 22 ) ) == 1.
!

private

    ^ ( long bitAt: ( 32 - 23 ) ) == 1.
!

protection

    ^ ( long bitAt: ( 32 - 15 ) ) == 1.
!

samplingFrequency

    "/ Original table from a MP3 documentation:
    "/
    "/    Bit 20    Bit 21  Dezimal  MPEG 1    MPEG 2
    "/    0         0       0        44100 Hz  22050 Hz
    "/    0         1       1        48000 Hz  24000 Hz
    "/    1         0       2        32000 Hz  16000 Hz
    "/    1         1       3        -         -

    | index |
    index := 1 + ( ( long copy bitAnd: 2r00000000000000000000110000000000 ) >> ( 32 - 22 ) ).

    index := index + ( 4 * ( self version - 1 ) ).

    ^ #( 44100 22050 48000 nil
         24000 32000 16000 nil ) at: index.
!

version

    "/ Original table from a MP3 documentation:
    "/
    "/    Bit 12   MPEG Version
    "/    0        MPEG 2
    "/    1        MPEG 1

    ^ 2 - ( long bitAt: ( 32 - 12 ) ).
! !

!MP3FileHeader class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libview2/ApplicationModel.st,v 1.146 2000-11-07 14:33:17 martin Exp $'
! !