Category talk:Wren-sound
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)) } }
}