Baby steps! Today I broke a music file into small pieces
using ffmpeg, then printed an ffmpeg playlist file
reflecting some logic, and used ffmpeg to mux the playlist
into an mp3. I didn't figure out streaming protocols yet.
I used a counter and common lisp's formatted output to name
files.
(setq *counter* (let ((count -1)) #| ... |#
(lambda ()
(values
(format nil "~5,'0d" (incf count))
count))))
(setf (symbol-function '*counter*)
(lambda () (funcall *counter*)))
;;Breaking out every 5 seconds
(dotimes (s (/ 167 5))
(multiple-value-bind (name count) (*counter*)
(let ((expression
(format nil
"ffmpeg -ss ~2,'0d:~2,'0d -i rancid.wav -t ~a chunks/~a.wav"
(truncate (* 5 count) 60) (rem (* 5 count) 60) 5 name)))
(ext:system expression))))
;;There's an ffmpeg expression in there somewhere.
Now let's do something and reassemble it.
(defun get-idx (path)
(parse-integer (subseq (file-namestring path) 0 5)))
(setq *paths* (directory #p"chunks/*.*"))
(setq *idxs* (mapcar 'get-idx *paths*))
(setq *idx.path* (mapcar 'list *idxs* *paths*))
(with-open-file (out #p"playlist.txt" :direction :output
:if-exists :supersede
:if-does-not-exist :create)
(dolist (s *idx.path*)
(when (evenp (first s))
(format out "file '~a'~%" (pathname (second s))))))
;;;;And let's stow that in an mp3 file using ffmpeg.
(ext:system
"ffmpeg -f concat -safe 0 -i playlist.txt -c copy output.wav")
;;I have an example (with more random numbers) here:
lynx
gopher://gopher.club/9/users/screwtape/3sanity.mp3 -dump > insanity.mp3
Some notes.
It seems like most audio formats don't like being sliced up
less than 5 seconds, but 5 second samples will run together
nicely. I guess it relates to chunking and/or compression. 5
seconds is really long with an fs of 44100. About (* 3 (expt
2 16)) samples (maybe using reflect extrapolation). A large
power-of-two fft and a length 3 prime fft.
Next I should figure out streaming to anon radio, and I can
noise up some silent moments.