add keyword arguments so functions work either big- or little-endian.
1 files changed, 40 insertions(+), 82 deletions(-)

M zmusic.el
M zmusic.el +40 -82
@@ 214,37 214,25 @@ a 0 C !"
   (should (equal (values-to-bytes "524946580000082457415645")
                  (zmusic//wave-header (make-list 2056 0)))))
 
-(defun zmusic//wave-header (data-subchunk)
+(cl-defun zmusic//wave-header (data-subchunk &optional (big-endian t))
   "Make a wave header, a list of bytes.
 
 The DATA-SUBCHUNK is the actual subchunk containing the data.  It has
-to be calculated before we get the header
-
-This assumes we're using big-endian numbers, plus PCM."
-  (values-to-bytes '(ASCII "RIFX")
-
-                    ;;size of file after this specific field. The whole file size - 8.
-                   `(b ,(+ 4 ;;rest of header
-                           24 ;;size of FMT chunk
-                           (length data-subchunk))
-                       4)
-                   '(ASCII "WAVE")))
-
-(defun zmusic//wave-header-little-endian (data-subchunk)
-    "Make a wave header, a list of bytes.
-
-The DATA-SUBCHUNK is the actual subchunk containing the data.  It has
 to be calculated before we get the header.
 
-This assumes we're using little-endian numbers, plus PCM."
-  (values-to-bytes '(ASCII "RIFF")
+BIG-ENDIAN controlls the endianness of the bytes here.
+
+This assumes we're using PCM."
+  (values-to-bytes (list 'ASCII (if big-endian
+                                    "RIFX"
+                                  "RIFF"))
 
                     ;;size of file after this specific field. The whole file size - 8.
                    `(b ,(+ 4 ;;rest of header
                            24 ;;size of FMT chunk
                            (length data-subchunk))
                        4
-                       nil)
+                       big-endian)
                    '(ASCII "WAVE")))
 
 (ert-deftest zmusic//sample-fmt ()

          
@@ 253,28 241,7 @@ This assumes we're using little-endian n
   (should (equal (values-to-bytes "666d74200000001000010002000056220001588800040010")
                  (zmusic//fmt-subchunk 22050))))
 
-(defun zmusic//fmt-subchunk (sample-rate)
-  "Make a fmt subchunk.
-
-SAMPLE-RATE is the number of samples per second.
-
-This assumes PCM and stereo, and works with big-endian numbers."
-  (let ((number-of-channels 2)
-        (bytes-per-sample 2))
-    (values-to-bytes '(ASCII "fmt ")
-                     '(b 16 4) ;;subchunk size -- PCM means no extra params.
-                     '(b 1 2) ;;PCM
-                     (list 'b number-of-channels 2)
-                     (list 'b sample-rate 4)
-                     (list 'b
-                           (* sample-rate number-of-channels bytes-per-sample)
-                           4)
-                     (list 'b
-                           (* number-of-channels bytes-per-sample)
-                           2)
-                     (list 'b (* 8 bytes-per-sample) 2))))
-
-(cl-defun zmusic//fmt-subchunk-little-endian (sample-rate &key (number-of-channels 2) (bytes-per-sample 2))
+(cl-defun zmusic//fmt-subchunk (sample-rate &key (number-of-channels 2) (bytes-per-sample 2) (big-endian t))
   "Make a fmt subchunk.
 
 SAMPLE-RATE is the number of samples per second.

          
@@ 283,21 250,23 @@ NUMBER-OF-CHANNELS is the number of audi
 
 BYTES-PER-SAMPLE is the number of bytes in each sample.
 
-This assumes PCM, and works with little-endian numbers."
+BIG-ENDIAN controlls the endianness.
+
+This assumes PCM."
   (values-to-bytes '(ASCII "fmt ")
-                   '(b 16 4 nil) ;;subchunk size -- PCM means no extra params.
-                   '(b 1 2 nil) ;;PCM
-                   (list 'b number-of-channels 2 nil)
-                   (list 'b sample-rate 4 nil)
+                   (list 'b 16 4 big-endian) ;;subchunk size -- PCM means no extra params.
+                   (list 'b 1 2 big-endian)  ;;PCM
+                   (list 'b number-of-channels 2 big-endian)
+                   (list 'b sample-rate 4 big-endian)
                    (list 'b
                          (* sample-rate number-of-channels bytes-per-sample)
                          4
-                         nil)
+                         big-endian)
                    (list 'b
                          (* number-of-channels bytes-per-sample)
                          2
-                         nil)
-                   (list 'b (* 8 bytes-per-sample) 2 nil)))
+                         big-endian)
+                   (list 'b (* 8 bytes-per-sample) 2 big-endian)))
 
 (defun rescale (value orig-low orig-high new-low new-high)
   "Rescales a VALUE in one range, to the equivalent value in another range.

          
@@ 350,16 319,12 @@ This returns a list of bytes, where two 
                                     data)
                    (zmusic//data-subchunk data)))))
 
-(defun zmusic//data-subchunk (raw-samples)
-  "Make a data subchunk from RAW-SAMPLES."
+(cl-defun zmusic//data-subchunk (raw-samples &optional (big-endian t))
+  "Make a data subchunk from RAW-SAMPLES.
+
+BIG-ENDIAN controlls the endianness."
   (values-to-bytes '(ASCII "data")
-                   (list 'b (length raw-samples) 4)
-                   raw-samples))
-
-(defun zmusic//data-subchunk-little-endian (raw-samples)
-  "Make a little-endian data subchunk from RAW-SAMPLES."
-  (values-to-bytes '(ASCII "data")
-                   (list 'b (length raw-samples) 4 nil)
+                   (list 'b (length raw-samples) 4 big-endian)
                    raw-samples))
 
 ;;zck should this all be arrays?

          
@@ 388,30 353,21 @@ This returns a list of bytes, where two 
                    (format "block align: %s\n" (seq-subseq wave-data 32 34))
                    (format "bits per sample: %s\n" (seq-subseq wave-data 34 36)))))
 
-(cl-defun zmusic//make-full-wave-data-little-endian (sample-rate music-data &key (number-of-channels 2) (bytes-per-sample 2))
+(cl-defun zmusic//make-full-wave-data (sample-rate music-data &key (number-of-channels 2) (bytes-per-sample 2) (big-endian t))
   "Make full wave data from the MUSIC-DATA, which is SAMPLE-RATE.
 
 NUMBER-OF-CHANNELS and BYTES-PER-SAMPLE are optional arguments.
 
-This assumes PCM, and works with little-endian numbers.
+BIG-ENDIAN controlls the endianness.
+
+This assumes PCM.
 
 This returns a vector of bytes."
-  (let ((data-subchunk (zmusic//data-subchunk-little-endian music-data)))
-    (vconcat (zmusic//wave-header-little-endian data-subchunk)
-             (zmusic//fmt-subchunk-little-endian sample-rate :number-of-channels number-of-channels :bytes-per-sample bytes-per-sample)
+  (let ((data-subchunk (zmusic//data-subchunk music-data big-endian)))
+    (vconcat (zmusic//wave-header data-subchunk big-endian)
+             (zmusic//fmt-subchunk sample-rate :number-of-channels number-of-channels :bytes-per-sample bytes-per-sample :big-endian big-endian)
              data-subchunk)))
 
-(defun zmusic//make-full-wave-data (sample-rate music-data)
-  "Make full wave data from the MUSIC-DATA, which is SAMPLE-RATE.
-
-This assumes PCM, stereo, big-endian"
-  (let ((data-subchunk (zmusic//data-subchunk music-data)))
-    (append (zmusic//wave-header data-subchunk)
-            (zmusic//fmt-subchunk sample-rate)
-            data-subchunk)))
-
-
-
 (defun write-bytes-to-file (bytes filename)
   "Write BYTES to FILENAME."
   ;;zck maybe also needs to bind (coding-system-for-write 'no-conversion)

          
@@ 608,10 564,11 @@ It is passed the path to a wave file."
                         (semitones-up (zmusic//scale-degree-to-semitones-up (1+ scale-degree)))
                         (duration (/ 60.0 *zmusic//bpm*))
                         (music-data (make-note semitones-up duration sample-rate :sample-size sample-size))
-                        (wave-data (zmusic//make-full-wave-data-little-endian sample-rate
+                        (wave-data (zmusic//make-full-wave-data sample-rate
                                                                               music-data
                                                                               :number-of-channels 1
-                                                                              :bytes-per-sample 1)))
+                                                                              :bytes-per-sample 1
+                                                                              :big-endian nil)))
                    (play-wave-data wave-data)))
        'follow-link t))))
 

          
@@ 710,10 667,11 @@ The samples are taken for DURATION at SA
   "Render SEMITONES, a list of semitones up from the root, into full wave data."
   (let* ((sample-rate 4410)
          (averaged-notes (zmusic//sample-semitones semitones (/ 60.0 *zmusic//bpm*) sample-rate))
-         (wave-data (zmusic//make-full-wave-data-little-endian sample-rate
-                                                               averaged-notes
-                                                               :number-of-channels 1
-                                                               :bytes-per-sample 1)))
+         (wave-data (zmusic//make-full-wave-data sample-rate
+                                                 averaged-notes
+                                                 :number-of-channels 1
+                                                 :bytes-per-sample 1
+                                                 :big-endian nil)))
         wave-data))
 
 (defun zmusic//render-beat-into-cache (beat-number)

          
@@ 1079,7 1037,7 @@ The file is given by FILE-TO-EXPORT-TO."
                                                   (/ 60.0 *zmusic//bpm*)
                                                   4410))
                       beats-as-semitones))
-         (wave-data (zmusic//make-full-wave-data-little-endian 4410 all-samples :number-of-channels 1 :bytes-per-sample 1)))
+         (wave-data (zmusic//make-full-wave-data 4410 all-samples :number-of-channels 1 :bytes-per-sample 1 :big-endian nil)))
     (write-bytes-to-file wave-data file-to-export-to)))
 
 (provide 'zmusic)