mp3duration.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. package common
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "io"
  6. "math"
  7. "mime/multipart"
  8. )
  9. import (
  10. "errors"
  11. )
  12. var (
  13. versions = []string{"2.5", "x", "2", "1"}
  14. layers = []string{"x", "3", "2", "1"}
  15. bitRates = map[string][]int{
  16. "V1Lx": []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  17. "V1L1": []int{0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448},
  18. "V1L2": []int{0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384},
  19. "V1L3": []int{0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320},
  20. "V2Lx": []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  21. "V2L1": []int{0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256},
  22. "V2L2": []int{0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160},
  23. "V2L3": []int{0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160},
  24. "VxLx": []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  25. "VxL1": []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  26. "VxL2": []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  27. "VxL3": []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  28. }
  29. sampleRates = map[string][]int{
  30. "x": []int{0, 0, 0},
  31. "1": []int{44100, 48000, 32000},
  32. "2": []int{22050, 24000, 16000},
  33. "2.5": []int{11025, 12000, 8000},
  34. }
  35. samples = map[string]map[string]int{
  36. "x": {
  37. "x": 0,
  38. "1": 0,
  39. "2": 0,
  40. "3": 0,
  41. },
  42. "1": { //MPEGv1, Layers 1,2,3
  43. "x": 0,
  44. "1": 384,
  45. "2": 1152,
  46. "3": 1152,
  47. },
  48. "2": { //MPEGv2/2.5, Layers 1,2,3
  49. "x": 0,
  50. "1": 384,
  51. "2": 1152,
  52. "3": 576,
  53. },
  54. }
  55. )
  56. type frame struct {
  57. bitRate int
  58. sampleRate int
  59. frameSize int
  60. sample int
  61. }
  62. func skipID3(buffer []byte) int {
  63. var id3v2Flags, z0, z1, z2, z3 byte
  64. var tagSize, footerSize int
  65. //http://id3.org/d3v2.3.0
  66. if buffer[0] == 0x49 && buffer[1] == 0x44 && buffer[2] == 0x33 { //'ID3'
  67. id3v2Flags = buffer[5]
  68. if (id3v2Flags & 0x10) != 0 {
  69. footerSize = 10
  70. } else {
  71. footerSize = 0
  72. }
  73. //ID3 size encoding is crazy (7 bits in each of 4 bytes)
  74. z0 = buffer[6]
  75. z1 = buffer[7]
  76. z2 = buffer[8]
  77. z3 = buffer[9]
  78. if ((z0 & 0x80) == 0) && ((z1 & 0x80) == 0) && ((z2 & 0x80) == 0) && ((z3 & 0x80) == 0) {
  79. tagSize = (((int)(z0 & 0x7f)) * 2097152) +
  80. (((int)(z1 & 0x7f)) * 16384) +
  81. (((int)(z2 & 0x7f)) * 128) +
  82. ((int)(z3 & 0x7f))
  83. return 10 + tagSize + footerSize
  84. }
  85. }
  86. return 0
  87. }
  88. func frameSize(samples int, layer string, bitRate, sampleRate, paddingBit int) int {
  89. if sampleRate == 0 {
  90. return 0
  91. } else if layer == "1" {
  92. return ((samples * bitRate * 125 / sampleRate) + paddingBit*4)
  93. } else { //layer 2, 3
  94. return (((samples * bitRate * 125) / sampleRate) + paddingBit)
  95. }
  96. }
  97. func parseFrameHeader(header []byte) *frame {
  98. b1 := header[1]
  99. b2 := header[2]
  100. versionBits := (b1 & 0x18) >> 3
  101. version := versions[versionBits]
  102. var simpleVersion string
  103. if version == "2.5" {
  104. simpleVersion = "2"
  105. } else {
  106. simpleVersion = version
  107. }
  108. layerBits := (b1 & 0x06) >> 1
  109. layer := layers[layerBits]
  110. bitRateKey := "V" + simpleVersion + "L" + layer
  111. bitRateIndex := (b2 & 0xf0) >> 4
  112. var bitRate int
  113. frameBitRates, exists := bitRates[bitRateKey]
  114. if exists && int(bitRateIndex) < len(frameBitRates) {
  115. bitRate = frameBitRates[bitRateIndex]
  116. } else {
  117. bitRate = 0
  118. }
  119. sampleRateIdx := (b2 & 0x0c) >> 2
  120. var sampleRate int
  121. frameSampleRates, exists := sampleRates[version]
  122. if exists && int(sampleRateIdx) < len(frameSampleRates) {
  123. sampleRate = frameSampleRates[sampleRateIdx]
  124. } else {
  125. sampleRate = 0
  126. }
  127. sample := samples[simpleVersion][layer]
  128. paddingBit := (b2 & 0x02) >> 1
  129. return &frame{
  130. bitRate: bitRate,
  131. sampleRate: sampleRate,
  132. frameSize: frameSize(sample, layer, bitRate, sampleRate, int(paddingBit)),
  133. sample: sample,
  134. }
  135. }
  136. func round(duration float64) float64 {
  137. return math.Round(duration*1000) / 1000 //round to nearest ms
  138. }
  139. // BoxHeader 信息头
  140. type BoxHeader2 struct {
  141. Size uint32
  142. FourccType [4]byte
  143. Size64 uint64
  144. }
  145. func getHeaderBoxInfo2(data []byte) (boxHeader BoxHeader2) {
  146. buf := bytes.NewBuffer(data)
  147. binary.Read(buf, binary.BigEndian, &boxHeader)
  148. return
  149. }
  150. // Calculate returns the duration of an mp3 file
  151. func GetMP3PlayDuration(file multipart.File) (duration float64, err error) {
  152. var size int64
  153. var info = make([]byte, 0x10)
  154. var boxHeader BoxHeader2
  155. file.ReadAt(info, 0)
  156. boxHeader = getHeaderBoxInfo2(info)
  157. size = int64(boxHeader.Size64)
  158. buffer := make([]byte, 100)
  159. if err != nil {
  160. return
  161. }
  162. var bytesRead int
  163. bytesRead, err = file.Read(buffer)
  164. if err != nil {
  165. return
  166. }
  167. if bytesRead < 100 {
  168. err = errors.New("Corrupt file")
  169. return
  170. }
  171. offset := int64(skipID3(buffer))
  172. buffer = make([]byte, 10)
  173. for offset < size {
  174. bytesRead, e := file.ReadAt(buffer, offset)
  175. if e != nil && e != io.EOF {
  176. err = e
  177. return
  178. }
  179. if bytesRead < 10 {
  180. duration = round(duration)
  181. return
  182. }
  183. if buffer[0] == 0xff && (buffer[1]&0xe0) == 0xe0 {
  184. info := parseFrameHeader(buffer)
  185. if info.frameSize > 0 && info.sample > 0 {
  186. offset += int64(info.frameSize)
  187. duration += (float64(info.sample) / float64(info.sampleRate))
  188. } else {
  189. offset++ //Corrupt file?
  190. }
  191. } else if buffer[0] == 0x54 && buffer[1] == 0x41 && buffer[2] == 0x47 { //'TAG'
  192. offset += 128 //Skip over id3v1 tag size
  193. } else {
  194. offset++ //Corrupt file?
  195. }
  196. }
  197. duration = round(duration)
  198. return
  199. }