mpeg.lisp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. ;;; -*- Mode: Lisp; show-trailing-whitespace: t; Base: 10; indent-tabs: nil; Syntax: ANSI-Common-Lisp; Package: MPEG; -*-
  2. ;;; Copyright (c) 2013, Mark VandenBrink. All rights reserved.
  3. (in-package #:mpeg)
  4. (log5:defcategory cat-log-mpeg-frame)
  5. (defmacro log-mpeg-frame (&rest log-stuff) `(log5:log-for (cat-log-mpeg-frame) ,@log-stuff))
  6. (define-condition mpeg-condition ()
  7. ((location :initarg :location :reader location :initform nil)
  8. (object :initarg :object :reader object :initform nil)
  9. (messsage :initarg :message :reader message :initform "Undefined Condition"))
  10. (:report (lambda (condition stream)
  11. (format stream "MP3 condition at location <~a> with object <~a>: message<~a>"
  12. (location condition) (object condition) (message condition)))))
  13. (define-condition mpeg-bad-header (mpeg-condition) ())
  14. (defconstant +sync-word+ #xffe0)
  15. (defconstant +mpeg-2.5+ 0)
  16. (defconstant +v-reserved+ 1)
  17. (defconstant +mpeg-2+ 2)
  18. (defconstant +mpeg-1+ 3)
  19. (defun valid-version (version)
  20. (or ;; can't deal with 2.5's yet (= (the fixnum +mpeg-2.5+) (the fixnum version))
  21. (= (the fixnum +mpeg-2+) (the fixnum version))
  22. (= (the fixnum +mpeg-1+) (the fixnum version))))
  23. (defun get-mpeg-version-string (version) (nth version '("MPEG 2.5" "Reserved" "MPEG 2" "MPEG 1")))
  24. (defconstant +layer-reserved+ 0)
  25. (defconstant +layer-3+ 1)
  26. (defconstant +layer-2+ 2)
  27. (defconstant +layer-1+ 3)
  28. (defun valid-layer (layer)
  29. (or (= (the fixnum +layer-3+) (the fixnum layer))
  30. (= (the fixnum +layer-2+) (the fixnum layer))
  31. (= (the fixnum +layer-1+) (the fixnum layer))))
  32. (defun get-layer-string (layer) (nth layer '("Reserved" "Layer III" "Layer II" "Layer I")))
  33. (defconstant +channel-mode-stereo+ 0)
  34. (defconstant +channel-mode-joint+ 1)
  35. (defconstant +channel-mode-dual+ 2)
  36. (defconstant +channel-mode-mono+ 3)
  37. (defun get-channel-mode-string (mode) (nth mode '("Stereo" "Joint" "Dual" "Mono")))
  38. (defconstant +emphasis-none+ 0)
  39. (defconstant +emphasis-50-15+ 1)
  40. (defconstant +emphasis-reserved+ 2)
  41. (defconstant +emphasis-ccit+ 3)
  42. (defun get-emphasis-string (e) (nth e '("None" "50/15 ms" "Reserved" "CCIT J.17")))
  43. (defun valid-emphasis (e) (or (= (the fixnum e) (the fixnum +emphasis-none+))
  44. (= (the fixnum e) (the fixnum +emphasis-50-15+))
  45. (= (the fixnum e) (the fixnum +emphasis-ccit+))))
  46. (defconstant +mode-extension-0+ 0)
  47. (defconstant +mode-extension-1+ 1)
  48. (defconstant +mode-extension-2+ 2)
  49. (defconstant +mode-extension-3+ 3)
  50. (defun get-mode-extension-string (channel-mode layer mode-extension)
  51. (if (not (= channel-mode +channel-mode-joint+))
  52. ""
  53. (if (or (= layer +layer-1+)
  54. (= layer +layer-2+))
  55. (format nil "Bands ~[4~;8~;12~;16~] to 31" mode-extension)
  56. (format nil "Intensity Stereo: ~[off~;on~], MS Stereo: ~[off~;on~]" (ash mode-extension -1) (logand mode-extension 1)))))
  57. (defun get-samples-per-frame (version layer)
  58. (cond ((= (the fixnum layer) (the fixnum +layer-1+)) 384)
  59. ((= (the fixnum layer) (the fixnum +layer-2+)) 1152)
  60. ((= (the fixnum layer) (the fixnum +layer-3+))
  61. (cond ((= (the fixnum version) +mpeg-1+) 1152)
  62. ((or (= (the fixnum version) (the fixnum +mpeg-2+))
  63. (= (the fixnum version) (the fixnum +mpeg-2.5+))) 576)))))
  64. (defclass frame ()
  65. ((pos :accessor pos :initarg :pos)
  66. (b-array :accessor b-array :initarg :b-array)
  67. (samples :accessor samples :initarg :samples)
  68. (sync :accessor sync :initarg :sync)
  69. (version :accessor version :initarg :version)
  70. (layer :accessor layer :initarg :layer)
  71. (protection :accessor protection :initarg :protection)
  72. (bit-rate :accessor bit-rate :initarg :bit-rate)
  73. (sample-rate :accessor sample-rate :initarg :sample-rate)
  74. (padded :accessor padded :initarg :padded)
  75. (private :accessor private :initarg :private)
  76. (channel-mode :accessor channel-mode :initarg :channel-mode)
  77. (mode-extension :accessor mode-extension :initarg :mode-extension)
  78. (copyright :accessor copyright :initarg :copyright)
  79. (original :accessor original :initarg :original)
  80. (emphasis :accessor emphasis :initarg :emphasis)
  81. (size :accessor size :initarg :size)
  82. (vbr :accessor vbr :initarg :vbr)
  83. (payload :accessor payload :initarg :payload))
  84. (:default-initargs :pos nil :b-array nil :samples 0 :sync 0 :version 0 :layer 0 :protection 0 :bit-rate 0
  85. :sample-rate 0 :padded 0 :private 0 :channel-mode 0 :mode-extension 0
  86. :copyright 0 :original 0 :emphasis 0 :size nil :vbr nil :payload nil))
  87. (defmacro with-frame-slots ((instance) &body body)
  88. `(with-slots (pos b-array samples sync version layer protection bit-rate sample-rate
  89. padded private channel-mode mode-extension copyright
  90. original emphasis size vbr payload) ,instance
  91. ,@body))
  92. (let ((bit-array-table
  93. (make-array '(14 5) :initial-contents
  94. '((32 32 32 32 8)
  95. (64 48 40 48 16)
  96. (96 56 48 56 24)
  97. (128 64 56 64 32)
  98. (160 80 64 80 40)
  99. (192 96 80 96 48)
  100. (224 112 96 112 56)
  101. (256 128 112 128 64)
  102. (288 160 128 144 80)
  103. (320 192 160 160 96)
  104. (352 224 192 176 112)
  105. (384 256 224 192 128)
  106. (416 320 256 224 144)
  107. (448 384 320 256 160)))))
  108. (defun valid-bit-rate-index (br-index)
  109. (and (> (the fixnum br-index) 0) (< (the fixnum br-index) 15)))
  110. (defun get-bit-rate (version layer bit-rate-index)
  111. (log5:with-context "get-bit-rate"
  112. (log-mpeg-frame "version = ~d, layer = ~d, bit-rate-index = ~d" version layer bit-rate-index)
  113. (let ((row (1- bit-rate-index))
  114. (col (cond ((= (the fixnum version) (the fixnum +mpeg-1+))
  115. (cond ((= (the fixnum layer) (the fixnum +layer-1+)) 0)
  116. ((= (the fixnum layer) (the fixnum +layer-2+)) 1)
  117. ((= (the fixnum layer) (the fixnum +layer-3+)) 2)
  118. (t nil)))
  119. ((= (the fixnum version) (the fixnum +mpeg-2+))
  120. (cond ((= (the fixnum layer) (the fixnum +layer-1+)) 3)
  121. ((= (the fixnum layer) (the fixnum +layer-2+)) 4)
  122. ((= (the fixnum layer) (the fixnum +layer-3+)) 4)
  123. (t nil)))
  124. (t (error "don't support MPEG 2.5 yet")))))
  125. (log-mpeg-frame "version = ~d, row = ~d, col = ~d" version row col)
  126. (if (or (null col) (< row 0) (> row 14))
  127. nil
  128. (let ((ret (* 1000 (aref bit-array-table row col))))
  129. (log-mpeg-frame "returning ~:d" ret)
  130. ret))))))
  131. (defun valid-sample-rate-index (sr-index)
  132. (and (>= (the fixnum sr-index) 0)
  133. (< (the fixnum sr-index) 3)))
  134. (defun get-sample-rate (version sr-index)
  135. (cond ((= (the fixnum version) (the fixnum +mpeg-1+))
  136. (case (the fixnum sr-index) (0 44100) (1 48000) (2 32000)))
  137. ((= (the fixnum version) (the fixnum +mpeg-2+))
  138. (case (the fixnum sr-index) (0 22050) (1 24000) (2 16000)))
  139. (t nil)))
  140. (defun get-frame-size (version layer bit-rate sample-rate padded)
  141. (truncate (float (cond ((= (the fixnum layer) (the fixnum +layer-1+))
  142. (* 4 (+ (/ (* 12 bit-rate) sample-rate) padded)))
  143. ((= (the fixnum layer) (the fixnum +layer-2+))
  144. (+ (* 144 (/ bit-rate sample-rate)) padded))
  145. ((= (the fixnum layer) (the fixnum +layer-3+))
  146. (if (= (the fixnum version) (the fixnum +mpeg-1+))
  147. (+ (* 144 (/ bit-rate sample-rate)) padded)
  148. (+ (* 72 (/ bit-rate sample-rate)) padded)))))))
  149. (defmethod load-frame ((me frame) &key instream (read-payload nil))
  150. (log5:with-context "load-frame"
  151. (with-frame-slots (me)
  152. (when (null b-array) ; has header already been read in?
  153. (setf pos (stream-seek instream 0 :current))
  154. (setf b-array (stream-read-sequence instream 4)))
  155. (if (parse-header me)
  156. (progn
  157. (log-mpeg-frame "header parsed ok")
  158. (setf size (get-frame-size version layer bit-rate sample-rate padded))
  159. (when read-payload
  160. (setf payload (stream-read-sequence instream (- size 4))))
  161. t)
  162. (progn
  163. (log-mpeg-frame "header didn't parse!")
  164. nil)))))
  165. (defmethod parse-header ((me frame))
  166. (log5:with-context "parse-header"
  167. (with-frame-slots (me)
  168. (setf (ldb (byte 8 8) sync) (aref b-array 0))
  169. (setf (ldb (byte 3 5) sync) (ldb (byte 3 5) (aref b-array 1)))
  170. (when (not (= sync +sync-word+))
  171. (return-from parse-header nil))
  172. (setf version (ldb (byte 2 3) (aref b-array 1)))
  173. (when (not (valid-version version))
  174. (log-mpeg-frame "bad version ~d" version)
  175. (return-from parse-header nil))
  176. (setf layer (ldb (byte 2 1) (aref b-array 1)))
  177. (when (not (valid-layer layer))
  178. (log-mpeg-frame "bad layer ~d" layer)
  179. (return-from parse-header nil))
  180. (setf protection (ldb (byte 1 0) (aref b-array 1)))
  181. (setf samples (get-samples-per-frame version layer))
  182. (let ((br-index (the fixnum (ldb (byte 4 4) (aref b-array 2)))))
  183. (when (not (valid-bit-rate-index br-index))
  184. (log-mpeg-frame "bad bit-rate index ~d" br-index)
  185. (return-from parse-header nil))
  186. (setf bit-rate (get-bit-rate version layer br-index)))
  187. (let ((sr-index (the fixnum (ldb (byte 2 2) (aref b-array 2)))))
  188. (when (not (valid-sample-rate-index sr-index))
  189. (log-mpeg-frame "bad sample-rate index ~d" sr-index)
  190. (return-from parse-header nil))
  191. (setf sample-rate (get-sample-rate version sr-index)))
  192. (setf padded (ldb (byte 1 1) (aref b-array 2)))
  193. (setf private (ldb (byte 1 0) (aref b-array 2)))
  194. (setf channel-mode (ldb (byte 2 6) (aref b-array 3)))
  195. (setf mode-extension (ldb (byte 2 4) (aref b-array 3)))
  196. (setf copyright (ldb (byte 1 3) (aref b-array 3)))
  197. (setf original (ldb (byte 1 2) (aref b-array 3)))
  198. (setf emphasis (ldb (byte 2 0) (aref b-array 3)))
  199. (when (not (valid-emphasis emphasis))
  200. (log-mpeg-frame "bad emphasis ~d" emphasis)
  201. (return-from parse-header nil))
  202. (log-mpeg-frame "good parse: ~a" me)
  203. t)))
  204. (defmethod vpprint ((me frame) stream)
  205. (with-frame-slots (me)
  206. (format stream "MPEG Frame: position in file = ~:d, header in (hex) bytes = ~x, size = ~d, sync word = ~x, " pos b-array size sync)
  207. (when vbr
  208. (format stream "~&vbr-info: ~a~%" vbr))
  209. (format stream "version = ~a, layer = ~a, crc protected? = ~[yes~;no~], bit-rate = ~:d bps, sampling rate = ~:d bps, padded? = ~[no~;yes~], private bit set? = ~[no~;yes~], channel mode = ~a, "
  210. (get-mpeg-version-string version) (get-layer-string layer)
  211. protection bit-rate sample-rate padded private (get-channel-mode-string channel-mode))
  212. (format stream "mode extension = ~a, copyrighted? = ~[no~;yes~], original? = ~[no~;yes~], emphasis = ~a"
  213. (get-mode-extension-string channel-mode layer mode-extension) copyright original (get-emphasis-string emphasis))
  214. (when payload
  215. (format stream "~%frame payload[~:d] = ~a~%" (length payload) payload))))
  216. (defclass vbr-info ()
  217. ((tag :accessor tag :initarg :tag)
  218. (flags :accessor flags :initarg :flags)
  219. (frames :accessor frames :initarg :frames)
  220. (bytes :accessor bytes :initarg :bytes)
  221. (tocs :accessor tocs :initarg :tocs)
  222. (scale :accessor scale :initarg :scale))
  223. (:default-initargs :tag nil :flags 0 :frames nil :bytes nil :tocs nil :scale nil))
  224. (defmacro with-vbr-info-slots ((instance) &body body)
  225. `(with-slots (tag flags frames bytes tocs scale) ,instance
  226. ,@body))
  227. (defconstant +vbr-frames+ 1)
  228. (defconstant +vbr-bytes+ 2)
  229. (defconstant +vbr-tocs+ 4)
  230. (defconstant +vbr-scale+ 8)
  231. (defun get-side-info-size (version channel-mode)
  232. (cond ((= (the fixnum version) (the fixnum +mpeg-1+))
  233. (cond ((= (the fixnum channel-mode) (the fixnum +channel-mode-mono+)) 17)
  234. (t 32)))
  235. (t (cond ((= (the fixnum channel-mode) (the fixnum +channel-mode-mono+)) 9)
  236. (t 17)))))
  237. (defmethod check-vbr ((me frame))
  238. (log5::with-context "check-vbr"
  239. (with-frame-slots (me)
  240. (let ((i (get-side-info-size version channel-mode)))
  241. (log-mpeg-frame "array index = ~d, payload size = ~d" i (length payload))
  242. (when (or (and (= (aref payload (+ i 0)) (char-code #\X))
  243. (= (aref payload (+ i 1)) (char-code #\i))
  244. (= (aref payload (+ i 2)) (char-code #\n))
  245. (= (aref payload (+ i 3)) (char-code #\g)))
  246. (and (= (aref payload (+ i 0)) (char-code #\I))
  247. (= (aref payload (+ i 1)) (char-code #\n))
  248. (= (aref payload (+ i 2)) (char-code #\f))
  249. (= (aref payload (+ i 3)) (char-code #\o))))
  250. (log-mpeg-frame "found xing/info: ~c ~c ~c ~c"
  251. (code-char (aref payload (+ i 0)))
  252. (code-char (aref payload (+ i 1)))
  253. (code-char (aref payload (+ i 2)))
  254. (code-char (aref payload (+ i 3))))
  255. (setf vbr (make-instance 'vbr-info))
  256. (let ((v (make-mem-stream (payload me))))
  257. (stream-seek v i :start) ; seek to xing/info info
  258. (setf (tag vbr) (stream-read-iso-string-with-len v 4))
  259. (setf (flags vbr) (stream-read-u32 v))
  260. (when (logand (flags vbr) +vbr-frames+)
  261. (setf (frames vbr) (stream-read-u32 v))
  262. (if (= 0 (frames vbr)) (warn-user "warning Xing/Info header flags has FRAMES set, but field is zero")))
  263. (when (logand (flags vbr) +vbr-bytes+)
  264. (setf (bytes vbr) (stream-read-u32 v))
  265. (if (= 0 (bytes vbr)) (warn-user "warning Xing/Info header flags has BYTES set, but field is zero")))
  266. (when (logand (flags vbr) +vbr-tocs+)
  267. (setf (tocs vbr) (stream-read-sequence v 100)))
  268. (when (logand (flags vbr) +vbr-scale+)
  269. (setf (scale vbr) (stream-read-u32 v)))
  270. (log-mpeg-frame "vbr-info = ~a" (vpprint vbr nil))))))))
  271. (defmethod vpprint ((me vbr-info) stream)
  272. (with-vbr-info-slots (me)
  273. (format stream "tag = ~a, flags = 0x~x, frames = ~:d, bytes = ~:d, tocs = ~d, scale = ~d, "
  274. tag flags frames bytes tocs scale)))
  275. (defun find-first-sync (in)
  276. (log5:with-context "find-first-sync"
  277. (log-mpeg-frame "Looking for first sync, begining at file position ~:d" (stream-seek in 0 :current))
  278. (let ((b-array (make-octets 4))
  279. (pos))
  280. (handler-case
  281. ;;
  282. ;; loop through entire file if we have to
  283. ;; XXX question: if we read FF E from the file (two bytes), but the
  284. ;; parse fails (i.e. a false sync), do we skip forward, or try to parse
  285. ;; the second byte as the FF?
  286. (loop
  287. (setf pos (stream-seek in 0 :current))
  288. (setf (aref b-array 0) (stream-read-u8 in))
  289. (when (= (aref b-array 0) #xff)
  290. (setf (aref b-array 1) (stream-read-u8 in))
  291. (when (= (logand (aref b-array 1) #xe0) #xe0)
  292. (log-mpeg-frame "Potential sync bytes at ~:d: <~x>" pos b-array)
  293. (setf (aref b-array 2) (stream-read-u8 in))
  294. (setf (aref b-array 3) (stream-read-u8 in))
  295. (let ((hdr (make-instance 'frame :b-array b-array :pos pos)))
  296. (if (load-frame hdr :instream in :read-payload t)
  297. (progn
  298. (check-vbr hdr)
  299. (log-mpeg-frame "Valid header being returned: ~a" hdr)
  300. (return-from find-first-sync hdr))
  301. (progn
  302. (log-mpeg-frame "hdr wasn't valid: ~a" hdr)))))))
  303. (end-of-file (c) (progn
  304. (log-mpeg-frame "got a condition while looking for first sync: ~a" c)
  305. (error c))))
  306. nil)))
  307. (defmethod next-frame ((me frame) &key instream read-payload)
  308. (log5:with-context "next-frame"
  309. (let ((nxt-frame (make-instance 'frame)))
  310. (when (not (payload me))
  311. (log-mpeg-frame "no payload in current frame, skipping from ~:d forward ~:d bytes"
  312. (stream-seek instream 0 :current)
  313. (- (size me) 4) :current)
  314. (stream-seek instream (- (size me) 4) :current))
  315. (if (load-frame nxt-frame :instream instream :read-payload read-payload)
  316. nxt-frame
  317. nil))))
  318. (defun map-frames (in func &key (start-pos nil) (read-payload nil) (max nil))
  319. (log5:with-context "next-frame"
  320. (log-mpeg-frame "mapping frame, start pos ~:d" start-pos)
  321. (when start-pos
  322. (stream-seek in start-pos :start))
  323. (loop
  324. for max-frames = (if max max most-positive-fixnum)
  325. for count = 0 then (incf count)
  326. for frame = (find-first-sync in) then (next-frame frame :instream in :read-payload read-payload)
  327. while (and frame (< count max-frames)) do
  328. (log-mpeg-frame "At pos ~:d, dispatching function" (pos frame))
  329. (funcall func frame))))
  330. (defun get-mpeg-bit-rate-exhaustive (in)
  331. (let ((n-frames 0)
  332. (total-len 0)
  333. (last-bit-rate nil)
  334. (bit-rate-total 0)
  335. (vbr nil))
  336. (map-frames in (lambda (f)
  337. (incf n-frames)
  338. (incf total-len (float (/ (samples f) (sample-rate f))))
  339. (incf bit-rate-total (bit-rate f))
  340. (if (null last-bit-rate)
  341. (setf last-bit-rate (bit-rate f))
  342. (progn
  343. (when (not (= last-bit-rate (bit-rate f)))
  344. (setf vbr t))
  345. (setf last-bit-rate (bit-rate f)))))
  346. :read-payload nil)
  347. (if (or (zerop n-frames) (zerop bit-rate-total))
  348. (values nil nil nil)
  349. (values vbr (float (/ bit-rate-total n-frames)) total-len))))
  350. (defun get-mpeg-bit-rate-ff (in)
  351. (let ((ff (find-first-sync in)))
  352. (if (not ff)
  353. (return-from get-mpeg-bit-rate-ff (values nil nil)))
  354. (if (vbr ff)
  355. (let* ((len (float (* (frames (vbr ff)) (/ (samples ff) (sample-rate ff)))))
  356. (br (float (/ (* 8 (bytes (vbr ff)) ) len))))
  357. (values t br len))
  358. (values nil nil nil))))
  359. (defclass mpeg-audio-info ()
  360. ((is-vbr :accessor is-vbr :initarg :is-vbr :initform nil)
  361. (bit-rate :accessor bit-rate :initarg :bit-rate :initform nil)
  362. (sample-rate :accessor sample-rate :initarg :sample-rate :initform nil)
  363. (len :accessor len :initarg :len :initform nil)
  364. (version :accessor version :initarg :version :initform nil)
  365. (layer :accessor layer :initarg :layer :initform nil)))
  366. (defmethod vpprint ((me mpeg-audio-info) stream)
  367. (with-slots (is-vbr sample-rate bit-rate len version layer) me
  368. (format stream "~a, ~a, ~:[CBR,~;VBR,~] sample rate: ~:d Hz, bit rate: ~:d Kbps, duration: ~:d:~2,'0d"
  369. (get-mpeg-version-string version)
  370. (get-layer-string layer)
  371. is-vbr
  372. sample-rate
  373. (round (/ bit-rate 1000))
  374. (floor (/ len 60)) (round (mod len 60)))))
  375. (defun get-mpeg-audio-info (in &key (max-frames nil))
  376. "Get MPEG Layer 3 audio information."
  377. (log5:with-context "get-mpeg-audio-info"
  378. (let ((pos (stream-seek in 0 :current))
  379. (first-frame (find-first-sync in))
  380. (info (make-instance 'mpeg-audio-info)))
  381. (log-mpeg-frame "search for first frame yielded ~a" first-frame)
  382. (when (null first-frame)
  383. (return-from get-mpeg-audio-info nil))
  384. (with-slots (is-vbr sample-rate bit-rate len version layer) info
  385. (setf version (version first-frame))
  386. (setf layer (layer first-frame))
  387. (setf sample-rate (sample-rate first-frame))
  388. (if (vbr first-frame)
  389. (progn
  390. (log-mpeg-frame "found Xing/Info header")
  391. (setf is-vbr t)
  392. (setf len (float (* (frames (vbr first-frame)) (/ (samples first-frame) (sample-rate first-frame)))))
  393. (setf bit-rate (float (/ (* 8 (bytes (vbr first-frame)) ) len))))
  394. (let ((n-frames 0)
  395. (total-len 0)
  396. (last-bit-rate nil)
  397. (bit-rate-total 0)
  398. (vbr nil))
  399. (stream-seek in pos :start)
  400. (log-mpeg-frame "no Xing/Info, so mapping frames")
  401. (map-frames in (lambda (f)
  402. (incf n-frames)
  403. (incf total-len (float (/ (samples f) (sample-rate f))))
  404. (incf bit-rate-total (bit-rate f))
  405. (if (null last-bit-rate)
  406. (setf last-bit-rate (bit-rate f))
  407. (progn
  408. (when (not (= last-bit-rate (bit-rate f)))
  409. (setf vbr t))
  410. (setf last-bit-rate (bit-rate f)))))
  411. :read-payload nil :max max-frames)
  412. (if (or (< n-frames 10) (zerop bit-rate-total))
  413. (progn
  414. (log-mpeg-frame "couldn't get audio-info: only got ~d frames" n-frames)
  415. (return-from get-mpeg-audio-info nil))
  416. (progn
  417. (setf is-vbr vbr)
  418. (setf len total-len)
  419. (setf bit-rate (float (/ bit-rate-total n-frames))))))))
  420. info)))
  421. #|
  422. if we have a xing header, we use
  423. num-frames, num-bytes from xing header and
  424. sample-rate and layer info (to get num samples/sec---for layer 3 its 1152)
  425. then:
  426. length in seconds is = num-frames * (1152 / sample-rate)
  427. bit-rate is = (8 * num-bytes) / length in seconds, then divide by 1000 to get kbits/sec
  428. ---------
  429. |#