Record sound
You are encouraged to solve this task according to the task description, using any language you may know.
Record a monophonic 16-bit PCM sound into either memory space, a file or array.
(This task neglects to specify the sample rate, and whether to use signed samples. The programs in this page might use signed 16-bit or unsigned 16-bit samples, at 8000 Hz, 44100 Hz, or any other sample rate. Therefore, these programs might not record sound in the same format.)
AutoHotkey
<lang autohotkey>name := "sample" waitsec := 5 Tooltip Recording %name%.wav MCI_SendString("close all wait") MCI_SendString("open new type waveaudio alias " . name) MCI_SendString("set " . name . " time format ms wait")
- MCI_SendString("set " . name . " bitspersample 16 wait")
- MCI_SendString("set " . name . " channels 1 wait")
- MCI_SendString("set " . name . " samplespersec 16000 wait")
- MCI_SendString("set " . name . " alignment 1 wait")
- MCI_SendString("set " . name . " bytespersec 8000 wait")
MCI_SendString("record " . name) Sleep waitsec*1000 MCI_SendString("stop " . name . " wait") MCI_SendString("save " . name . " """ . name . ".wav""") Tooltip Finished ... Playing MCI_SendString("delete " . name) MCI_SendString("close " . name . " wait") MCI_SendString("open """ . name . ".wav"" type waveaudio alias " . name) MCI_SendString("play " . name . " wait") MCI_SendString("close " . name . " wait") Tooltip Return
MCI_SendString(p_lpszCommand,ByRef r_lpszReturnString="",p_hwndCallback=0) { VarSetCapacity(r_lpszReturnString,512,0) Return DllCall("winmm.dll\mciSendString" . (A_IsUnicode ? "W":"A") ,"Str",p_lpszCommand ;-- lpszCommand ,"Str",r_lpszReturnString ;-- lpszReturnString ,"UInt",512 ;-- cchReturn ,A_PtrSize ? "Ptr":"UInt",p_hwndCallback ;-- hwndCallback ,"Cdecl Int") ;-- Return type }
- For more intuitive functions, see the MCI library by jballi.
- doc
- http://www.autohotkey.net/~jballi/MCI/v1.1/MCI.html
- download
- http://www.autohotkey.net/~jballi/MCI/v1.1/MCI.ahk</lang>
BBC BASIC
<lang bbcbasic> wavfile$ = @dir$ + "capture.wav"
bitspersample% = 16 channels% = 2 samplespersec% = 44100 alignment% = bitspersample% * channels% / 8 bytespersec% = alignment% * samplespersec% params$ = " bitspersample " + STR$(bitspersample%) + \ \ " channels " + STR$(channels%) + \ \ " alignment " + STR$(alignment%) + \ \ " samplespersec " + STR$(samplespersec%) + \ \ " bytespersec " + STR$(bytespersec%) SYS "mciSendString", "close all", 0, 0, 0 SYS "mciSendString", "open new type waveaudio alias capture", 0, 0, 0 SYS "mciSendString", "set capture" + params$, 0, 0, 0 TO res% IF res% ERROR 100, "Couldn't set capture parameters: " + STR$(res% AND &FFFF) PRINT "Press SPACE to start recording..." REPEAT UNTIL INKEY(1) = 32 SYS "mciSendString", "record capture", 0, 0, 0 TO res% IF res% ERROR 100, "Couldn't start audio capture: " + STR$(res% AND &FFFF) PRINT "Recording, press SPACE to stop..." REPEAT UNTIL INKEY(1) = 32 SYS "mciSendString", "stop capture", 0, 0, 0 SYS "mciSendString", "save capture " + wavfile$, 0, 0, 0 TO res% IF res% ERROR 100, "Couldn't save to WAV file: " + STR$(res% AND &FFFF) SYS "mciSendString", "delete capture", 0, 0, 0 SYS "mciSendString", "close capture", 0, 0, 0 PRINT "Captured audio is stored in " wavfile$</lang>
C
Read/write raw device /dev/dsp
. On Linux you need access to said device, meaning probably you should be in audio user group.
<lang c>#include <stdlib.h>
- include <unistd.h>
- include <sys/types.h>
- include <fcntl.h>
void * record(size_t bytes) { int fd; if (-1 == (fd = open("/dev/dsp", O_RDONLY))) return 0; void *a = malloc(bytes); read(fd, a, bytes); close(fd); return a; }
int play(void *buf, size_t len) { int fd; if (-1 == (fd = open("/dev/dsp", O_WRONLY))) return 0; write(fd, buf, len); close(fd); return 1; }
int main() { void *p = record(65536); play(p, 65536); return 0; }</lang>
C++
Uses Windows MCI <lang cpp>
- include <iostream>
- include <string>
- include <windows.h>
- include <mmsystem.h>
- pragma comment ( lib, "winmm.lib" )
using namespace std;
class recorder { public:
void start() {
paused = rec = false; action = "IDLE"; while( true ) { cout << endl << "==" << action << "==" << endl << endl; cout << "1) Record" << endl << "2) Play" << endl << "3) Pause" << endl << "4) Stop" << endl << "5) Quit" << endl; char c; cin >> c; if( c > '0' && c < '6' ) { switch( c ) { case '1': record(); break; case '2': play(); break; case '3': pause(); break; case '4': stop(); break; case '5': stop(); return; } } }
}
private:
void record() {
if( mciExecute( "open new type waveaudio alias my_sound") ) { mciExecute( "record my_sound" ); action = "RECORDING"; rec = true; }
} void play() {
if( paused ) mciExecute( "play my_sound" ); else if( mciExecute( "open tmp.wav alias my_sound" ) ) mciExecute( "play my_sound" );
action = "PLAYING"; paused = false;
} void pause() {
if( rec ) return; mciExecute( "pause my_sound" ); paused = true; action = "PAUSED";
} void stop() {
if( rec ) { mciExecute( "stop my_sound" ); mciExecute( "save my_sound tmp.wav" ); mciExecute( "close my_sound" ); action = "IDLE"; rec = false; } else { mciExecute( "stop my_sound" ); mciExecute( "close my_sound" ); action = "IDLE"; }
} bool mciExecute( string cmd ) {
if( mciSendString( cmd.c_str(), NULL, 0, NULL ) ) { cout << "Can't do this: " << cmd << endl; return false; } return true;
}
bool paused, rec; string action;
};
int main( int argc, char* argv[] ) {
recorder r; r.start(); return 0;
} </lang>
ChucK
<lang c>// chuck this with other shreds to record to file // example> chuck foo.ck bar.ck rec
// arguments: rec:<filename>
// get name me.arg(0) => string filename; if( filename.length() == 0 ) "foo.wav" => filename;
// pull samples from the dac dac => Gain g => WvOut w => blackhole; // this is the output file name filename => w.wavFilename; <<<"writing to file:", "'" + w.filename() + "'">>>; // any gain you want for the output .5 => g.gain;
// temporary workaround to automatically close file on remove-shred null @=> w;
// infinite time loop... // ctrl-c will stop it, or modify to desired duration while( true ) 1::second => now;</lang>
Common Lisp
<lang lisp> (defun record (n)
(with-open-file (in "/dev/dsp" :element-type '(unsigned-byte 8)) (loop repeat n collect (read-byte in)) ) )
(defun play (byte-list)
(with-open-file (out "/dev/dsp" :direction :output :element-type '(unsigned-byte 8) :if-exists :append) (mapcar (lambda (b) (write-byte b out)) byte-list) ) )
(play (record 65536)) </lang>
Go
As Go does not have any audio support in its standard library, this invokes the 'arecord' command-line utility to record sound from the internal microphone (assuming there's no other audio input device present) and saves it to a monophonic, signed 16-bit .wav file. It then plays it back using the 'aplay' utility.
The file name, sampling rate and duration can all be set by the user. <lang go>package main
import (
"bufio" "fmt" "log" "os" "os/exec" "strconv"
)
func check(err error) {
if err != nil { log.Fatal(err) }
}
func main() {
scanner := bufio.NewScanner(os.Stdin) name := "" for name == "" { fmt.Print("Enter output file name (without extension) : ") scanner.Scan() name = scanner.Text() check(scanner.Err()) } name += ".wav"
rate := 0 for rate < 2000 || rate > 192000 { fmt.Print("Enter sampling rate in Hz (2000 to 192000) : ") scanner.Scan() input := scanner.Text() check(scanner.Err()) rate, _ = strconv.Atoi(input) } rateS := strconv.Itoa(rate)
dur := 0.0 for dur < 5 || dur > 30 { fmt.Print("Enter duration in seconds (5 to 30) : ") scanner.Scan() input := scanner.Text() check(scanner.Err()) dur, _ = strconv.ParseFloat(input, 64) } durS := strconv.FormatFloat(dur, 'f', -1, 64)
fmt.Println("OK, start speaking now...") // Default arguments: -c 1, -t wav. Note only signed 16 bit format supported. args := []string{"-r", rateS, "-f", "S16_LE", "-d", durS, name} cmd := exec.Command("arecord", args...) err := cmd.Run() check(err)
fmt.Printf("'%s' created on disk and will now be played back...\n", name) cmd = exec.Command("aplay", name) err = cmd.Run() check(err) fmt.Println("Play-back completed.")
}</lang>
Diego
This funct
ion returns a {wav}
variable recorded from a thing in the mist. It understands that the found thing
has a microphone, so will have microphone knowledge. If the caller does not have microphone knowledge, the callee will train the caller on first request.
<lang diego>begin_funct({wav}, Record sound);
set_decision(linger); find_thing()_first()_microphone()_bitrate(16)_tech(PCM)_samplerate(signed16, unsigned16)_rangefrom(8000, Hz)_rangeto(44100, Hz)_export(.wav) ? with_found()_microphone()_label(mic); : err_funct[]_err(Sorry, no one has a microphone!); exit_funct[]; ; with_microphone[mic]_record()_durat({secs}, 30)_var(recording); [Record sound]_ret([recording]); reset_decision();
end_funct[];
// Record a monophonic 16-bit PCM sound into memory space: exec_funct(Record sound)_var(PCMRecording)_me(); // The variable 'PCMRecording' is the sound in memory space
// Record a monophonic 16-bit PCM sound into a file or array: exec_funct(Record sound)_file(foo.wav)_me(); // The file 'foo.wav' is the sound in a file</lang>
This is the instruct
ion version, where the thing keeps the reocording.
<lang diego>begin_instruct(Record sound);
set_decision(linger); find_thing()_first()_microphone()_bitrate(16)_tech(PCM)_samplerate(signed16, unsigned16)_rangefrom(8000, Hz)_rangeto(44100, Hz)_export(.wav) ? with_found()_label(recorder)_microphone()_label(mic); : err_instruct[]_err(Sorry, no one has a microphone!); exit_instruct[]; ; with_microphone[mic]_record()_durat({secs}, 30)_var(recording); reset_decision();
end_instruct[];
// Record a monophonic 16-bit PCM sound into memory space: exec_instruct(Record sound)_me(); with_thing[recorder]_microphone[mic]_var[recording]_var(PCMRecording); // The variable 'PCMRecording' is the sound in memory space
// Record a monophonic 16-bit PCM sound into a file or array: exec_instruct(Record sound)_me(); with_thing[recorder]_microphone[mic]_var[recording]_file(foo.wav)_me(); // The file 'foo.wav' is the sound in a file</lang>
GUISS
Here we activate the Microsoft Windows '95 Sound Recorder:
<lang guiss>Start,Programs,Accessories,Sound Recorder,Button:Record</lang>
Julia
<lang Julia> using PortAudio, LibSndFile
stream = PortAudioStream("Microphone (USB Microphone)", 1, 0) # 44100 samples/sec buf = read(stream, 441000) save("recorded10sec.wav", buf) </lang>
Kotlin
<lang scala>// version 1.1.3
import java.io.File import javax.sound.sampled.*
const val RECORD_TIME = 20000L // twenty seconds say
fun main(args: Array<String>) {
val wavFile = File("RecordAudio.wav") val fileType = AudioFileFormat.Type.WAVE val format = AudioFormat(16000.0f, 16, 2, true, true) val info = DataLine.Info(TargetDataLine::class.java, format) val line = AudioSystem.getLine(info) as TargetDataLine
// Creates a new thread that waits for 'RECORD_TIME' before stopping Thread(object: Runnable { override fun run() { try { Thread.sleep(RECORD_TIME) } catch (ie: InterruptedException) { println(ie.message) } finally { line.stop() line.close() } println("Finished") } }).start()
// Captures the sound and saves it in a WAV file try { if (AudioSystem.isLineSupported(info)) { line.open(format) line.start() println("Recording started") AudioSystem.write(AudioInputStream(line), fileType, wavFile) } else println("Line not supported") } catch (lue: LineUnavailableException) { println(lue.message) }
}</lang>
Liberty BASIC
LB can easily send a MCI string to the OS, or extra routines eg SOX, so a minimal solution could be <lang lb> run "sndrec32.exe" </lang> A more direct way is.. <lang lb>
print "Starting 5 sec. recording..." r$ =mciSendString$( "open new type waveaudio alias capture") r$ =mciSendString$( "set capture time format ms bitspersample 16") r$ =mciSendString$( "set capture channels 1 samplespersec 8000") r$ =mciSendString$( "set capture alignment 1 bytespersec 8000") r$ =mciSendString$( "record capture") timer 5000, [on] wait [on] timer 0 print " .... now stopping the recording." r$ =mciSendString$( "stop capture") r$ =mciSendString$( "save capture " +chr$( 34) +"sample.wav" +chr$( 34)) r$ =mciSendString$( "close capture") print "Done recording." r$=mciSendString$( "open " +q$ +"sample.wav" +q$ +" type waveaudio alias sfx") r$=mciSendString$( "play sfx wait") r$=mciSendString$( "close sfx") print "Done playing back." end
function mciSendString$( s$)
print s$ buffer$ =space$( 1024) +chr$( 0) calldll #winmm, "mciSendStringA", s$ as ptr, buffer$ as ptr, 1028 as long, 0 as long, r as long buffer$ =left$( buffer$, instr( buffer$, chr$( 0)) -1) if r >0 then mciSendString$ ="error" print "returned "; mciSendString$ else mciSendString$ =""'buffer$ print "OK" end if
end function </lang>
LiveCode
This example sets some aspects of a sound recording individually and also shows use of the sound input dialog where a user can conveniently set them as well, either may be used.<lang LiveCode>command makeRecording
set the dontUseQT to false -- on windows use true set the recordFormat to "wave" -- can be wav,aiff, au set the recordRate to 44.1 -- sample at 44100 Hz set the recordSampleSize to 16 --default is 8 bit ask file "Save recording as" if it is not empty then answer record --show sound input dialog with presets above record sound file it -- actual record command wait 10 seconds stop recording end if
end makeRecording</lang>
Mathematica /Wolfram Language
<lang Mathematica>SystemDialogInput["RecordSound"]</lang>
Nim
This code is for Linux systems and uses “arecord” and “aplay”. Previous code which used “/dev/dsp” no longer works on modern OS. This code is a direct translation from Go version, but uses integers instead of floats for duration. <lang nim>import osproc, strutils
var name = "" while name.len == 0:
stdout.write "Enter output file name (without extension): " name = stdin.readLine().strip()
name.add ".wav"
var rate = 0 while rate notin 2000..19_200:
stdout.write "Enter sampling rate in Hz (2000 to 192000): " try: rate = parseInt(stdin.readLine().strip()) except ValueError: discard
var duration = 0 while duration notin 5..30:
stdout.write "Enter duration in seconds (5 to 30): " try: duration = parseInt(stdin.readLine().strip()) except ValueError: discard
echo "OK, start speaking now..."
- Default arguments: -c 1, -t wav. Note that only signed 16 bit format is supported.
let args = ["-r", $rate, "-f", "S16_LE", "-d", $duration, name] echo execProcess("arecord", args = args, options = {poStdErrToStdOut, poUsePath})
echo "'$1' created on disk and will now be played back..." % name echo execProcess("aplay", args = [name], options = {poStdErrToStdOut, poUsePath}) echo "Playback completed"</lang>
OCaml
<lang ocaml>#load "unix.cma"
let record bytes =
let buf = String.make bytes '\000' in let ic = open_in "/dev/dsp" in let chunk = 4096 in for i = 0 to pred (bytes / chunk) do ignore (input ic buf (i * chunk) chunk) done; close_in ic; (buf)
let play buf len =
let oc = open_out "/dev/dsp" in output_string oc buf; close_out oc
let () =
let bytes = 65536 in let p = record bytes in play p bytes</lang>
Phix
-- -- demo\rosetta\Record_sound.exw -- ============================= -- without js -- (file i/o) constant wavfile = "capture.wav", bitspersample = 16, channels = 2, samplespersec = 44100, alignment = bitspersample * channels / 8, bytespersec = alignment * samplespersec, params = sprintf(" bitspersample %d channels %d alignment %d samplespersec %d bytespersec %d", {bitspersample, channels, alignment, samplespersec, bytespersec}), error_size = 2048 atom winmm = NULL, xmciSendString, pError procedure mciSendString(string msg) if winmm=NULL then winmm = open_dll("winmm.dll") xmciSendString = define_c_func(winmm,"mciSendStringA", {C_PTR, -- LPCTSTR lpszCommand C_PTR, -- LPTSTR lpszReturnString C_INT, -- UINT cchReturn C_PTR}, -- HANDLE hwndCallback C_INT) -- MCIERROR pError = allocate(error_size) end if atom res = c_func(xmciSendString,{msg,pError,error_size,NULL}) if res!=0 then crash("error %0x: %s",{res,peek_string(pError)}) end if end procedure include get.e -- get_bytes() function record(integer bytes) integer fn = open("/dev/dsp","rb") if fn=-1 then return "" end if string res = get_bytes(fn,bytes) close(fn) return res end function procedure play(string buf) if length(buf) then integer fn = open("/dev/dsp","wb") if fn!=-1 then puts(fn,buf) close(fn) end if end if end procedure if platform()=WINDOWS then mciSendString("close all") mciSendString("open new type waveaudio alias capture") mciSendString("set capture" & params) puts(1,"Press SPACE to start recording...") while wait_key()!=' ' do end while mciSendString("record capture") puts(1,"Recording, press SPACE to stop...") while wait_key()!=' ' do end while mciSendString("stop capture") mciSendString("save capture " & wavfile) mciSendString("delete capture") mciSendString("close capture") puts(1,"Captured audio is stored in "&wavfile) elsif platform()=LINUX then -- warning: untested play(record(65536)) -- -- alternative, from Go (ditto) -- string name = "test.wav", -- rate = "2000", -- (2000..192000 Hz) -- durn = "5" -- (5 to 30 seconds) -- printf(1,"OK, start speaking now...\n") -- -- Default arguments: -c 1, -t wav. Note only signed 16 bit format supported. -- string cmd = sprintf("arecord -r %s -f S16_LE -d %s %s", {rate,durn,name}) -- {} = system_exec(cmd) -- printf(1,"'%s' created on disk and will now be played back...\n", {name}) -- {} = system_exec("aplay "&name) -- printf(1,"Play-back completed.\n") end if
PicoLisp
<lang PicoLisp>(in '(rec -q -c1 -tu16 - trim 0 2) # Record 2 seconds
(make (while (rd 2) (link @) ) ) )</lang>
Output:
-> (16767 19071 17279 ... 5503 9343 14719) # 96000 numbers
Python
<lang python>import pyaudio
chunk = 1024 FORMAT = pyaudio.paInt16 CHANNELS = 1 RATE = 44100
p = pyaudio.PyAudio()
stream = p.open(format = FORMAT,
channels = CHANNELS, rate = RATE, input = True, frames_per_buffer = chunk)
data = stream.read(chunk) print [ord(i) for i in data]</lang>
Racket
<lang racket>
- lang racket
(define (record n) (with-input-from-file "/dev/dsp" ( () (read-bytes n)))) (define (play bs) (display-to-file bs "/dev/dsp" #:exists 'append)) (play (record 65536)) </lang>
Raku
(formerly Perl 6)
Slightly modified from an example provided with the Audio::PortAudio
module distribution.
<lang perl6>use Audio::PortAudio;
use Audio::Sndfile;
sub MAIN(Str $filename, Str :$source, Int :$buffer = 256) {
my $pa = Audio::PortAudio.new; my $format = Audio::Sndfile::Info::Format::WAV +| Audio::Sndfile::Info::Subformat::PCM_16; my $out-file = Audio::Sndfile.new(:$filename, channels => 1, samplerate => 44100, :$format, :w); my $st; if $source.defined { my $index = 0; for $pa.devices -> $device { if $device.name eq $source { else { my $la = $device.default-high-input-latency; my $si = Audio::PortAudio::StreamParameters.new(device => $index, channel-count => 1, sample-format => Audio::PortAudio::StreamFormat::Float32, suggested-latency => ($la || 0.05e0 )); $st = $pa.open-stream($si, Audio::PortAudio::StreamParameters, 44100, $buffer ); last; }
} $index++; } die "Couldn't find a device for '$source'" if !$st.defined; } else { $st = $pa.open-default-stream(2,0, Audio::PortAudio::StreamFormat::Float32, 44100, $buffer); } $st.start; my $p = Promise.new; signal(SIGINT).act({ say "stopping recording"; $p.keep: "stopped"; $out-file.close; $st.close; exit; }); my Channel $write-channel = Channel.new; my $write-promise = start { react { whenever $write-channel -> $item { if $p.status ~~ Planned { $out-file.write-float($item[0], $item[1]); $out-file.sync; } else { done; } } } };
loop { if $p.status ~~ Planned { my $f = $buffer || $st.read-available; if $f > 0 { my $buff = $st.read($f,2, num32); $write-channel.send([$buff, $f]); } } else { last; } }
}</lang>
Scala
<lang Scala>import java.io.{File, IOException} import javax.sound.sampled.{AudioFileFormat, AudioFormat, AudioInputStream} import javax.sound.sampled.{AudioSystem, DataLine, LineUnavailableException, TargetDataLine}
object SoundRecorder extends App {
// record duration, in milliseconds final val RECORD_TIME = 60000 // 1 minute
// path and format of the wav file val (wavFile, fileType) = (new File("RecordAudio.wav"), AudioFileFormat.Type.WAVE) val format = new AudioFormat(/*sampleRate =*/ 16000f, /*sampleSizeInBits =*/ 16, /*channels =*/ 2, /*signed =*/ true, /*bigEndian =*/ true)
val info = new DataLine.Info(classOf[TargetDataLine], format) val line: TargetDataLine = AudioSystem.getLine(info).asInstanceOf[TargetDataLine]
// Entry to run the program
// Creates a new thread that waits for a specified of time before stopping new Thread(new Runnable() { def run() { try { Thread.sleep(RECORD_TIME) } catch { case ex: InterruptedException => ex.printStackTrace() } finally { line.stop() line.close() } println("Finished") } }).start()
//Captures the sound and record into a WAV file try { // checks if system supports the data line if (AudioSystem.isLineSupported(info)) { line.open(format) line.start() // start capturing println("Recording started") AudioSystem.write(new AudioInputStream(line), fileType, wavFile) } else println("Line not supported") } catch { case ex: LineUnavailableException => ex.printStackTrace() case ioe: IOException => ioe.printStackTrace() }
}</lang>
Tcl
<lang tcl>package require sound
- Helper to do a responsive wait
proc delay t {after $t {set ::doneDelay ok}; vwait ::doneDelay}
- Make an in-memory recording object
set recording [snack::sound -encoding "Lin16" -rate 44100 -channels 1]
- Set it doing the recording, wait for a second, and stop
$recording record -append true delay 1000 $recording stop
- Convert the internal buffer to viewable numbers, and print them out
binary scan [$recording data -byteorder littleEndian] s* words puts [join $words ", "]
- Destroy the recording object
$recording destroy</lang>
Wee Basic
<lang Wee Basic>print 1 "Recording..." micrec print 1 "Playing..." micpla end</lang>
Wren
The ability to call external processes such as arecord is expected to be added to Wren-cli in the next release. In the meantime, we embed the following Wren script in a C host to complete this task. <lang ecmascript>/* record_sound.wren */
class C {
foreign static getInput(maxSize)
foreign static arecord(args)
foreign static aplay(name)
}
var name = "" while (name == "") {
System.write("Enter output file name (without extension) : ") name = C.getInput(80)
} name = name + ".wav"
var rate = 0 while (!rate || !rate.isInteger || rate < 2000 || rate > 192000) {
System.write("Enter sampling rate in Hz (2000 to 192000) : ") rate = Num.fromString(C.getInput(6))
} var rateS = rate.toString
var dur = 0 while (!dur || dur < 5 || dur > 30) {
System.write("Enter duration in seconds (5 to 30) : ") dur = Num.fromString(C.getInput(5))
} var durS = dur.toString
System.print("\nOK, start speaking now...") // Default arguments: -c 1, -t wav. Note only signed 16 bit format supported. var args = ["-r", rateS, "-f", "S16_LE", "-d", durS, name] C.arecord(args.join(" "))
System.print("\n'%(name)' created on disk and will now be played back...")
C.aplay(name)
System.print("\nPlay-back completed.")</lang>
We now embed this in the following C program, compile and run it.
<lang c>#include <stdio.h>
- include <stdio_ext.h>
- include <stdlib.h>
- include <string.h>
- include "wren.h"
void C_getInput(WrenVM* vm) {
int maxSize = (int)wrenGetSlotDouble(vm, 1) + 2; char input[maxSize]; fgets(input, maxSize, stdin); __fpurge(stdin); input[strcspn(input, "\n")] = 0; wrenSetSlotString(vm, 0, (const char*)input);
}
void C_arecord(WrenVM* vm) {
const char *args = wrenGetSlotString(vm, 1); char command[strlen(args) + 8]; strcpy(command, "arecord "); strcat(command, args); system(command);
}
void C_aplay(WrenVM* vm) {
const char *name = wrenGetSlotString(vm, 1); char command[strlen(name) + 6]; strcpy(command, "aplay "); strcat(command, name); system(command);
}
WrenForeignMethodFn bindForeignMethod(
WrenVM* vm, const char* module, const char* className, bool isStatic, const char* signature) { if (strcmp(module, "main") == 0) { if (strcmp(className, "C") == 0) { if (isStatic && strcmp(signature, "getInput(_)") == 0) return C_getInput; if (isStatic && strcmp(signature, "arecord(_)") == 0) return C_arecord; if (isStatic && strcmp(signature, "aplay(_)") == 0) return C_aplay; } } return NULL;
}
static void writeFn(WrenVM* vm, const char* text) {
printf("%s", text);
}
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
switch (errorType) { case WREN_ERROR_COMPILE: printf("[%s line %d] [Error] %s\n", module, line, msg); break; case WREN_ERROR_STACK_TRACE: printf("[%s line %d] in %s\n", module, line, msg); break; case WREN_ERROR_RUNTIME: printf("[Runtime Error] %s\n", msg); break; }
}
char *readFile(const char *fileName) {
FILE *f = fopen(fileName, "r"); fseek(f, 0, SEEK_END); long fsize = ftell(f); rewind(f); char *script = malloc(fsize + 1); fread(script, 1, fsize, f); fclose(f); script[fsize] = 0; return script;
}
int main(int argc, char **argv) {
WrenConfiguration config; wrenInitConfiguration(&config); config.writeFn = &writeFn; config.errorFn = &errorFn; config.bindForeignMethodFn = &bindForeignMethod; WrenVM* vm = wrenNewVM(&config); const char* module = "main"; const char* fileName = "record_sound.wren"; char *script = readFile(fileName); WrenInterpretResult result = wrenInterpret(vm, module, script); switch (result) { case WREN_RESULT_COMPILE_ERROR: printf("Compile Error!\n"); break; case WREN_RESULT_RUNTIME_ERROR: printf("Runtime Error!\n"); break; case WREN_RESULT_SUCCESS: break; } wrenFreeVM(vm); free(script); return 0;
}</lang>
- Programming Tasks
- Sound
- Temporal media
- AWK/Omit
- Brlcad/Omit
- HTML/Omit
- LFE/Omit
- Logtalk/Omit
- Lotus 123 Macro Scripting/Omit
- Maxima/Omit
- ML/I/Omit
- Openscad/Omit
- PARI/GP/Omit
- TI-83 BASIC/Omit
- TPP/Omit
- Zkl/Omit
- AutoHotkey
- BBC BASIC
- Batch File/Omit
- C
- C++
- ChucK
- Common Lisp
- Go
- Diego
- GUISS
- Julia
- Kotlin
- Liberty BASIC
- LiveCode
- Mathematica
- Wolfram Language
- Nim
- OCaml
- Phix
- PicoLisp
- Python
- Racket
- Raku
- Scala
- Tcl
- Snack
- Wee Basic
- Wren