github.com/bluenviron/mediacommon@v1.9.3/pkg/codecs/mpeg1audio/frame_header.go (about) 1 package mpeg1audio 2 3 import ( 4 "fmt" 5 ) 6 7 // http://www.mp3-tech.org/programmer/frame_header.html 8 var bitrates = [][][]int{ 9 // MPEG-1 10 { 11 // layer 1 12 {}, 13 // layer 2 14 { 15 32000, 16 48000, 17 56000, 18 64000, 19 80000, 20 96000, 21 112000, 22 128000, 23 160000, 24 192000, 25 224000, 26 256000, 27 320000, 28 384000, 29 }, 30 // layer 3 31 { 32 32000, 33 40000, 34 48000, 35 56000, 36 64000, 37 80000, 38 96000, 39 112000, 40 128000, 41 160000, 42 192000, 43 224000, 44 256000, 45 320000, 46 }, 47 }, 48 // MPEG-2 49 { 50 // layer 1 51 {}, 52 // layer 2 53 { 54 8000, 55 16000, 56 24000, 57 32000, 58 40000, 59 48000, 60 56000, 61 64000, 62 80000, 63 96000, 64 112000, 65 128000, 66 144000, 67 160000, 68 }, 69 // layer 3 70 { 71 8000, 72 16000, 73 24000, 74 32000, 75 40000, 76 48000, 77 56000, 78 64000, 79 80000, 80 96000, 81 112000, 82 128000, 83 144000, 84 160000, 85 }, 86 }, 87 } 88 89 var sampleRates = [][]int{ 90 // MPEG-1 91 { 92 44100, 93 48000, 94 32000, 95 }, 96 // MPEG-2 97 { 98 22050, 99 24000, 100 16000, 101 }, 102 } 103 104 var samplesPerFrame = [][]int{ 105 // MPEG-1 106 { 107 384, 108 1152, 109 1152, 110 }, 111 // MPEG-2 112 { 113 384, 114 1152, 115 576, 116 }, 117 } 118 119 // ChannelMode is a channel mode of a MPEG-1/2 audio frame. 120 type ChannelMode int 121 122 // standard channel modes. 123 const ( 124 ChannelModeStereo ChannelMode = 0 125 ChannelModeJointStereo ChannelMode = 1 126 ChannelModeDualChannel ChannelMode = 2 127 ChannelModeMono ChannelMode = 3 128 ) 129 130 // FrameHeader is the header of a MPEG-1/2 audio frame. 131 // Specification: ISO 11172-3, 2.4.1.3 132 type FrameHeader struct { 133 MPEG2 bool 134 Layer uint8 135 Bitrate int 136 SampleRate int 137 Padding bool 138 ChannelMode ChannelMode 139 } 140 141 // Unmarshal decodes a FrameHeader. 142 func (h *FrameHeader) Unmarshal(buf []byte) error { 143 if len(buf) < 5 { 144 return fmt.Errorf("not enough bytes") 145 } 146 147 syncWord := uint16(buf[0])<<4 | uint16(buf[1])>>4 148 if syncWord != 0x0FFF { 149 return fmt.Errorf("sync word not found: %x", syncWord) 150 } 151 152 h.MPEG2 = ((buf[1] >> 3) & 0x01) == 0 153 154 var mpegIndex int 155 if h.MPEG2 { 156 mpegIndex = 1 157 } else { 158 mpegIndex = 0 159 } 160 161 h.Layer = 4 - ((buf[1] >> 1) & 0b11) 162 if h.Layer <= 1 || h.Layer >= 4 { 163 return fmt.Errorf("unsupported MPEG layer: %v", h.Layer) 164 } 165 166 bitrateIndex := (buf[2] >> 4) 167 if bitrateIndex == 0 || bitrateIndex >= 15 { 168 return fmt.Errorf("invalid bitrate") 169 } 170 h.Bitrate = bitrates[mpegIndex][h.Layer-1][bitrateIndex-1] 171 172 sampleRateIndex := (buf[2] >> 2) & 0b11 173 if sampleRateIndex >= 3 { 174 return fmt.Errorf("invalid sample rate") 175 } 176 h.SampleRate = sampleRates[mpegIndex][sampleRateIndex] 177 178 h.Padding = ((buf[2] >> 1) & 0b1) != 0 179 h.ChannelMode = ChannelMode(buf[3] >> 6) 180 181 return nil 182 } 183 184 // FrameLen returns the length of the frame associated with the header. 185 func (h FrameHeader) FrameLen() int { 186 if h.Padding { 187 return (144 * h.Bitrate / h.SampleRate) + 1 188 } 189 return (144 * h.Bitrate / h.SampleRate) 190 } 191 192 // SampleCount returns the number of samples contained into the frame. 193 func (h FrameHeader) SampleCount() int { 194 var mpegIndex int 195 if h.MPEG2 { 196 mpegIndex = 1 197 } else { 198 mpegIndex = 0 199 } 200 201 return samplesPerFrame[mpegIndex][h.Layer-1] 202 }