Record sound

From Rosetta Code
Revision as of 12:29, 29 January 2014 by rosettacode>Son0p
Task
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.)

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>

  1. include <unistd.h>
  2. include <sys/types.h>
  3. 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>


ChucK

<lang c>// chuck this with other shreds to record to file // example> chuck foo.ck bar.ck rec (see also rec2.ck)

// 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>


GUISS

Here we activate the Microsoft Windows '95 Sound Recorder:

<lang guiss>Start,Programs,Accessories,Sound Recorder,Button:Record</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>

Mathematica

<lang Mathematica>SystemDialogInput["RecordSound"]</lang>

OCaml

Translation of: C

<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>

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

Translation of: C

<lang racket>

  1. 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>

Tcl

Library: Snack

<lang tcl>package require sound

  1. Helper to do a responsive wait

proc delay t {after $t {set ::doneDelay ok}; vwait ::doneDelay}

  1. Make an in-memory recording object

set recording [snack::sound -encoding "Lin16" -rate 44100 -channels 1]

  1. Set it doing the recording, wait for a second, and stop

$recording record -append true delay 1000 $recording stop

  1. Convert the internal buffer to viewable numbers, and print them out

binary scan [$recording data -byteorder littleEndian] s* words puts [join $words ", "]

  1. Destroy the recording object

$recording destroy</lang>