Category talk:Wren-sound

From Rosetta Code
Revision as of 09:24, 4 June 2021 by PureFox (talk | contribs) (Added source code for new 'Wren-sound' module.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Source code

<lang ecmascript>/* Module "sound.wren" */

import "io" for File

/* Wav enables the creation of simple .wav files for playing by external utiliies. */ class Wav {

   // Private method to convert a 16-bit unsigned integer 'x'
   // to a list of 2 bytes in little-endian format.
   static fromInt16LE_(x) {
       var bytes = List.filled(2, 0)
       bytes[0] = x         & 255
       bytes[1] = (x >> 8)  & 255
       return bytes
   }
   // Private method to convert a 32-bit unsigned integer 'x'
   // to a list of 4 bytes in little-endian format.
   static fromInt32LE_(x) {
       var bytes = List.filled(4, 0)
       bytes[0] = x         & 255
       bytes[1] = (x >> 8)  & 255
       bytes[2] = (x >> 16) & 255
       bytes[3] = (x >> 24) & 255
       return bytes
   }
   // Creates or overwrites an existing .wav file on disk using the given sample rate.
   // Such files are always single channel and use the PCM format.
   static create(filePath, data, sampleRate) {
       if (filePath.type != String) Fiber.abort("File path must be a string.")
       if (data.type != List || data.count == 0 || data[0].type != Num || !data[0].isInteger) {
           Fiber.abort("Data must be a non-empty list of whdr.")
       }
       if (sampleRate.type != Num || !sampleRate.isInteger || sampleRate < 1) {
           Fiber.abort("Sample rate must be a positive integer.")
       }
       var dataLength = data.count
       var hdrSize = 44
       var fileLen = dataLength + hdrSize - 8  // file size - 8
       // buffers
       var buf2 = List.filled(2, 0)
       var buf4 = List.filled(4, 0)
       // WAV header
       var whdr = []
       whdr.addAll("RIFF".bytes)
       whdr.addAll(fromInt32LE_(fileLen))    // fileLen
       whdr.addAll("WAVE".bytes)
       whdr.addAll("fmt ".bytes)
       whdr.addAll(fromInt32LE_(16))         // length of format data (= 16)
       var temp = fromInt16LE_(1)
       whdr.addAll(temp)                     // type of format (= 1 (PCM))
       whdr.addAll(temp)                     // number of channels (= 1)
       var temp2 = fromInt32LE_(sampleRate)
       whdr.addAll(temp2)                    // sample rate (= sr)
       whdr.addAll(temp2)                    // sr * bps(8) * channels(1) / 8 (= sr)
       whdr.addAll(temp)                     // bps(8) * channels(1) / 8 (= 1)
       whdr.addAll(fromInt16LE_(8))          // bits per sample (= 8)
       whdr.addAll("data".bytes)
       whdr.addAll(fromInt32LE_(dataLength)) // size of data section
       // write header and data to file
       File.create(filePath) { |file|
           for (b in whdr) file.writeBytes(String.fromByte(b))
           for (b in data) file.writeBytes(String.fromByte(b))            
       }
   }

}