From f8888ef61496b8039d72c74b7e825d2d95922a37 Mon Sep 17 00:00:00 2001 From: Rob Watson Date: Tue, 26 Jan 2021 17:08:40 +0100 Subject: [PATCH] continue development --- main.go | 70 ++++++++++++++++++++++++++++++---------------- main_test.go | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 24 deletions(-) diff --git a/main.go b/main.go index fac0117..bcc49d1 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,7 @@ import ( "os" ) -const fname = "/home/rob/share/home-office/example.mp3" +const fname = "/home/rob/home-office/example.mp3" type ( AudioVersionId int @@ -32,32 +32,55 @@ const ( LayerIndexI ) +var sampleRates = [5][16]uint32{ + {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0}, + {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0}, + {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}, + {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0}, + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, +} + func (h header) AudioVersionId() AudioVersionId { - b := h >> 8 - if b&0x18 == 0x18 { - return AudioVersionMPEG1 - } - if b&0x10 == 0x10 { - return AudioVersionMPEG2 - } - if b&0x8 == 0x8 { - return AudioVersionReserved - } - return AudioVersionMPEG25 + return AudioVersionId(((h >> 8) & 0x18) >> 3) } func (h header) LayerIndex() LayerIndex { - b := h >> 8 - if b&0x6 == 0x6 { - return LayerIndexI + return LayerIndex(((h >> 8) & 0x6) >> 1) +} + +func (h header) IsPrivate() bool { + return (h>>8)&1 == 1 +} + +func (h header) SampleRate() uint32 { + var j int + switch h.AudioVersionId() { + case AudioVersionMPEG1: + switch h.LayerIndex() { + case LayerIndexIII: + j = 2 + case LayerIndexII: + j = 1 + case LayerIndexI: + j = 0 + default: + return 0 + } + case AudioVersionReserved: + return 0 + case AudioVersionMPEG2, AudioVersionMPEG25: + switch h.LayerIndex() { + case LayerIndexIII, LayerIndexII: + j = 4 + case LayerIndexI: + j = 3 + default: + return 0 + + } } - if b&0x4 == 0x4 { - return LayerIndexII - } - if b&0x2 == 0x2 { - return LayerIndexIII - } - return LayerIndexReserved + k := ((h >> 20) & 0xf) + return sampleRates[j][k] } func main() { @@ -80,9 +103,8 @@ func main() { } header, err := newHeaderFromBytes(buf) - if err == nil { - fmt.Printf("Got header: %08X, audio version: %d\n", header, header.AudioVersionId()) + fmt.Printf("Got header: %08X, audio version: %d, layer index: %d\n", header, header.AudioVersionId(), header.LayerIndex()) } i++ diff --git a/main_test.go b/main_test.go index e2dc941..797497a 100644 --- a/main_test.go +++ b/main_test.go @@ -46,3 +46,82 @@ func TestLayerIndex(t *testing.T) { require.NoError(t, err) assert.Equal(t, LayerIndexI, h.LayerIndex()) } + +func TestIsPrivate(t *testing.T) { + bytes := []byte{0xff, 0xe1, 0, 0} + h, err := newHeader(binary.LittleEndian.Uint32(bytes)) + require.NoError(t, err) + assert.True(t, h.IsPrivate()) + + bytes = []byte{0xff, 0xe0, 0, 0} + h, err = newHeader(binary.LittleEndian.Uint32(bytes)) + require.NoError(t, err) + assert.False(t, h.IsPrivate()) +} + +func TestSampleRate(t *testing.T) { + testCases := []struct { + name string + bytes []byte + expSampleRate uint32 + }{ + { + "empty header", + []byte{0, 0, 0, 0}, + 0, + }, + { + "MPEG1 LayerI 32kbps", + []byte{0xff, 0xfe, 0x10, 0}, + 32, + }, + { + "MPEG1 LayerI 448kbps", + []byte{0xff, 0xfe, 0xe0, 0}, + 448, + }, + { + "MPEG1 LayerII 32kbps", + []byte{0xff, 0xfc, 0x10, 0}, + 32, + }, + { + "MPEG1 LayerII 448kbps", + []byte{0xff, 0xfc, 0xe0, 0}, + 384, + }, + { + "MPEG1 LayerIII 32kbps", + []byte{0xff, 0xfa, 0x10, 0}, + 32, + }, + { + "MPEG1 LayerIII 128kbps", + []byte{0xff, 0xfa, 0x90, 0}, + 128, + }, + { + "MPEG1 LayerIII 160kbps", + []byte{0xff, 0xfa, 0xa0, 0}, + 160, + }, + { + "MPEG1 LayerIII 320kbps", + []byte{0xff, 0xfa, 0xe0, 0x0}, + 320, + }, + { + "MPEG1 LayerIII reserved", + []byte{0xff, 0xfa, 0xf0, 0x0}, + 0, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + h, err := newHeader(binary.LittleEndian.Uint32(tc.bytes)) + require.NoError(t, err) + assert.Equal(t, tc.expSampleRate, h.SampleRate()) + }) + } +}