From 784042d3606db1bd3bbf8a8ea5f15c31cbb73ef6 Mon Sep 17 00:00:00 2001 From: aartaka Date: Thu, 31 Mar 2022 14:01:30 +0500 Subject: [PATCH 1/4] also-alsa: Minor indentation fixes. --- also-alsa.lisp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/also-alsa.lisp b/also-alsa.lisp index 4dcaf60..8a87e32 100644 --- a/also-alsa.lisp +++ b/also-alsa.lisp @@ -167,7 +167,7 @@ (defun alsa-element-type (type) (cond ((equalp type '(signed-byte 16)) :int16) - ((eql type 'single-float) :float) + ((eql type 'single-float) :float) ((eql type 'double-float) :double) ((equalp type '(unsigned-byte 8)) :uint8) ((equalp type '(signed-byte 8)) :int8) @@ -215,7 +215,7 @@ (defun alsa-open (device buffer-size element-type &key direction (sample-rate 44100) (channels-count 2) buffer) (when buffer (assert (and (subtypep (type-of buffer) 'simple-array) - (subtypep (array-element-type buffer) element-type)))) + (subtypep (array-element-type buffer) element-type)))) (let ((pcs (make-instance 'pcm-stream :direction (case direction (:input :snd-pcm-stream-capture) @@ -223,7 +223,7 @@ :device device :element-type element-type :buffer (or buffer - (make-alsa-buffer :element-type element-type :size buffer-size :channels channels-count)) + (make-alsa-buffer :element-type element-type :size buffer-size :channels channels-count)) :buffer-size (* buffer-size channels-count) ;number of samples really :channels-count channels-count :sample-rate sample-rate @@ -311,7 +311,7 @@ (snd-pcm-writei (deref (handle pcm)) ptr expected)))) (cond ((= result (- +epipe+)) ;; Under run, so prepare and retry - (alsa-warn "Underrun!") + (alsa-warn "Underrun!") (snd-pcm-prepare (deref (handle pcm))) (alsa-write pcm)) ((/= result expected) @@ -323,8 +323,8 @@ (snd-pcm-readi (deref (handle pcm)) ptr (/ (buffer-size pcm) (channels-count pcm)))))) (unless (= result (/ (buffer-size pcm) (channels-count pcm))) (if (eql result (- +epipe+)) - (progn (alsa-warn "Underrun!") (snd-pcm-prepare (deref (handle pcm)))) - (error "ALSA error: ~A" result))) + (progn (alsa-warn "Underrun!") (snd-pcm-prepare (deref (handle pcm)))) + (error "ALSA error: ~A" result))) pcm)) (defmethod contents-to-lisp ((pcm pcm-stream)) From 18032b752fb8972067bfc57fa8a5c4be399c9457 Mon Sep 17 00:00:00 2001 From: aartaka Date: Thu, 31 Mar 2022 14:02:31 +0500 Subject: [PATCH 2/4] also-alsa: Allow non-usb8 buffer contents. --- also-alsa.lisp | 82 +++++++++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/also-alsa.lisp b/also-alsa.lisp index 8a87e32..736a980 100644 --- a/also-alsa.lisp +++ b/also-alsa.lisp @@ -210,7 +210,7 @@ pcs) (defun make-alsa-buffer (&key element-type size channels) - (cffi:make-shareable-byte-vector (* (cffi:foreign-type-size (alsa-element-type element-type)) size channels))) + (make-array (* size channels) :element-type element-type)) (defun alsa-open (device buffer-size element-type &key direction (sample-rate 44100) (channels-count 2) buffer) (when buffer @@ -234,33 +234,35 @@ (:documentation "Reopens the stream. If all parameters are the same, just keeps the exiting one.")) (defmethod alsa-reopen ((pcs pcm-stream) device buffer-size element-type &key direction (sample-rate 44100) (channels-count 2)) - (if (or (eql (status pcs) :initial) - (not (and (equal device (device pcs)) - (= (* buffer-size channels-count) (buffer-size pcs)) - (equal element-type (element-type pcs)) - (eql direction (case (direction pcs) - (:snd-pcm-stream-capture :input) - (:snd-pcm-stream-playback :output))) - (= sample-rate (sample-rate pcs)) - (= channels-count (channels-count pcs))))) - (progn - (when (eql (status pcs) :open) - (alsa-close pcs)) - (alsa-open-2 (reinitialize-instance pcs - :direction (case direction - (:input :snd-pcm-stream-capture) - (:output :snd-pcm-stream-playback)) - :device device - :element-type element-type - :buffer (cffi:make-shareable-byte-vector - (* (cffi:foreign-type-size (alsa-element-type element-type)) buffer-size channels-count)) - #+nil(foreign-alloc (alsa-element-type element-type) - :count (* (cffi:foreign-type-size (alsa-element-type element-type)) buffer-size channels-count)) - :buffer-size (* buffer-size channels-count) ;number of samples really - :channels-count channels-count - :sample-rate sample-rate - :pcm-format (to-alsa-format element-type)))) - (snd-pcm-drop (deref (handle pcs)))) + (if (or (eql (status pcs) :initial) + (not (and (equal device (device pcs)) + (= (* buffer-size channels-count) (buffer-size pcs)) + (equal element-type (element-type pcs)) + (eql direction (case (direction pcs) + (:snd-pcm-stream-capture :input) + (:snd-pcm-stream-playback :output))) + (= sample-rate (sample-rate pcs)) + (= channels-count (channels-count pcs))))) + (progn + (when (eql (status pcs) :open) + (alsa-close pcs)) + (alsa-open-2 (reinitialize-instance + pcs + :direction (case direction + (:input :snd-pcm-stream-capture) + (:output :snd-pcm-stream-playback)) + :device device + :element-type element-type + :buffer (make-alsa-buffer :element-type element-type + :size buffer-size + :channels channels-count) + #+nil(foreign-alloc (alsa-element-type element-type) + :count (* (cffi:foreign-type-size (alsa-element-type element-type)) buffer-size channels-count)) + :buffer-size (* buffer-size channels-count) ;number of samples really + :channels-count channels-count + :sample-rate sample-rate + :pcm-format (to-alsa-format element-type)))) + (snd-pcm-drop (deref (handle pcs)))) pcs) (defmethod ref ((pcm pcm-stream) position) @@ -307,8 +309,11 @@ (defmethod alsa-write ((pcm pcm-stream)) (assert (eql (direction pcm) :snd-pcm-stream-playback)) (let* ((expected (/ (buffer-size pcm) (channels-count pcm))) - (result (with-pointer-to-vector-data (ptr (buffer pcm)) - (snd-pcm-writei (deref (handle pcm)) ptr expected)))) + (element-type (array-element-type (buffer pcm))) + (cffi-type (cffi::ensure-parsed-base-type + (list :array (alsa-element-type element-type) expected))) + (result (with-foreign-array (ptr (buffer pcm) cffi-type) + (snd-pcm-writei (deref (handle pcm)) ptr expected)))) (cond ((= result (- +epipe+)) ;; Under run, so prepare and retry (alsa-warn "Underrun!") @@ -319,20 +324,21 @@ (defmethod alsa-read ((pcm pcm-stream)) (assert (eql (direction pcm) :snd-pcm-stream-capture)) - (let ((result (with-pointer-to-vector-data (ptr (buffer pcm)) - (snd-pcm-readi (deref (handle pcm)) ptr (/ (buffer-size pcm) (channels-count pcm)))))) + (let* ((expected (/ (buffer-size pcm) (channels-count pcm))) + (element-type (array-element-type (buffer pcm))) + (cffi-type (cffi::ensure-parsed-base-type + (list :array (alsa-element-type element-type) expected))) + (result (with-foreign-array (ptr (buffer pcm) cffi-type) + (prog1 + (snd-pcm-readi (deref (handle pcm)) ptr expected) + (setf (slot-value pcm 'buffer) + (foreign-array-to-lisp ptr cffi-type :element-type element-type)))))) (unless (= result (/ (buffer-size pcm) (channels-count pcm))) (if (eql result (- +epipe+)) (progn (alsa-warn "Underrun!") (snd-pcm-prepare (deref (handle pcm)))) (error "ALSA error: ~A" result))) pcm)) -(defmethod contents-to-lisp ((pcm pcm-stream)) - (let ((result (make-array (buffer-size pcm) :element-type (element-type pcm)))) - (loop for i from 0 below (buffer-size pcm) do - (setf (aref result i) (ref pcm i))) - result)) - (defmacro with-alsa-device ((stream device buffer-size element-type &key direction (sample-rate 44100) (channels-count 2) buffer) &body body) (assert direction) `(let ((,stream (also-alsa:alsa-open ,device ,buffer-size ,element-type From 83fa716a2f6d5b7e01198568a2a380c1f23ca583 Mon Sep 17 00:00:00 2001 From: aartaka Date: Sat, 9 Apr 2022 22:48:57 +0500 Subject: [PATCH 3/4] also-alsa: Optimize for the usb8-typed buffers. --- also-alsa.lisp | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/also-alsa.lisp b/also-alsa.lisp index 736a980..aa04e06 100644 --- a/also-alsa.lisp +++ b/also-alsa.lisp @@ -210,7 +210,9 @@ pcs) (defun make-alsa-buffer (&key element-type size channels) - (make-array (* size channels) :element-type element-type)) + (if (equalp element-type '(unsigned-byte 8)) + (cffi:make-shareable-byte-vector (* size channels)) + (make-array (* size channels) :element-type element-type))) (defun alsa-open (device buffer-size element-type &key direction (sample-rate 44100) (channels-count 2) buffer) (when buffer @@ -310,10 +312,14 @@ (assert (eql (direction pcm) :snd-pcm-stream-playback)) (let* ((expected (/ (buffer-size pcm) (channels-count pcm))) (element-type (array-element-type (buffer pcm))) - (cffi-type (cffi::ensure-parsed-base-type - (list :array (alsa-element-type element-type) expected))) - (result (with-foreign-array (ptr (buffer pcm) cffi-type) - (snd-pcm-writei (deref (handle pcm)) ptr expected)))) + (result (if (equalp element-type '(unsigned-byte 8)) + (with-pointer-to-vector-data (ptr (buffer pcm)) + (snd-pcm-writei (deref (handle pcm)) ptr expected)) + (with-foreign-array + (ptr (buffer pcm) + (cffi::ensure-parsed-base-type + (list :array (alsa-element-type element-type) expected))) + (snd-pcm-writei (deref (handle pcm)) ptr expected))))) (cond ((= result (- +epipe+)) ;; Under run, so prepare and retry (alsa-warn "Underrun!") @@ -326,13 +332,17 @@ (assert (eql (direction pcm) :snd-pcm-stream-capture)) (let* ((expected (/ (buffer-size pcm) (channels-count pcm))) (element-type (array-element-type (buffer pcm))) - (cffi-type (cffi::ensure-parsed-base-type - (list :array (alsa-element-type element-type) expected))) - (result (with-foreign-array (ptr (buffer pcm) cffi-type) - (prog1 - (snd-pcm-readi (deref (handle pcm)) ptr expected) - (setf (slot-value pcm 'buffer) - (foreign-array-to-lisp ptr cffi-type :element-type element-type)))))) + (result (if (equalp element-type '(unsigned-byte 8)) + (with-pointer-to-vector-data (ptr (buffer pcm)) + (snd-pcm-readi (deref (handle pcm)) ptr expected)) + (with-foreign-array + (ptr (buffer pcm) + (cffi::ensure-parsed-base-type + (list :array (alsa-element-type element-type) expected))) + (prog1 + (snd-pcm-readi (deref (handle pcm)) ptr expected) + (setf (slot-value pcm 'buffer) + (foreign-array-to-lisp ptr cffi-type :element-type element-type))))))) (unless (= result (/ (buffer-size pcm) (channels-count pcm))) (if (eql result (- +epipe+)) (progn (alsa-warn "Underrun!") (snd-pcm-prepare (deref (handle pcm)))) From 9897619d3eaf73f6cbf9cc63c091dbafa52e9d4c Mon Sep 17 00:00:00 2001 From: aartaka Date: Sun, 19 Jun 2022 14:52:17 +0500 Subject: [PATCH 4/4] README: Update the example to comply with the non-usb8 shift. --- README.md | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 0b49541..f418479 100644 --- a/README.md +++ b/README.md @@ -12,15 +12,12 @@ To play random noise on one channel of default stereo device: (defconstant +channels+ 2) (also-alsa:with-alsa-device (pcm "sysdefault" +buffer-size+ '(signed-byte 16) :direction :output - :channels-count +channels+ :sample-rate +sample-rate+) + :channels-count +channels+ :sample-rate +sample-rate+) (also-alsa:alsa-start pcm) - (loop repeat 2 do - (loop with buffer = (also-alsa:buffer pcm) - for pos from 0 below (* +channels+ (also-alsa:buffer-size pcm)) by (* 2 +channels+) - for sample = (coerce (- (random 65535) 32767) '(signed-byte 16)) do - (setf (aref buffer pos) (logand sample #xff)) - (setf (aref buffer (1+ pos)) (logand (ash sample -8) #xff)) - (multiple-value-bind (avail delay) (also-alsa:get-avail-delay pcm) - (also-alsa:alsa-write pcm))))) - + (loop with buffer = (also-alsa:buffer pcm) + for pos from 0 below (also-alsa:buffer-size pcm) + for sample = (coerce (- (random 65535) 32767) '(signed-byte 16)) do + (setf (aref buffer pos) sample) + (multiple-value-bind (avail delay) (also-alsa:get-avail-delay pcm) + (also-alsa:alsa-write pcm)))) ```