Record sound: Difference between revisions
(omission list extended) |
(sort) |
||
(60 intermediate revisions by 35 users not shown) | |||
Line 1: | Line 1: | ||
{{task|Sound}} [[Category:Temporal media]] |
|||
{{task}} |
|||
{{omit from|AWK}} |
|||
{{omit from|Brlcad}} |
|||
{{omit from|HTML}} |
|||
{{omit from|LFE}} |
|||
{{omit from|Logtalk}} |
|||
{{omit from|Lotus 123 Macro Scripting}} |
|||
{{omit from|Maxima}} |
|||
{{omit from|ML/I}} |
|||
{{omit from|Openscad}} |
|||
{{omit from|PARI/GP}} |
|||
{{omit from|TI-83 BASIC}} |
|||
{{omit from|TPP}} |
|||
{{omit from|zkl}} |
|||
Record a monophonic 16-bit PCM sound into either memory space, a file or array. |
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.) |
|||
=={{header|AutoHotkey}}== |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
=={{header|BBC BASIC}}== |
|||
{{works with|BBC BASIC for Windows}} |
|||
<syntaxhighlight 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$</syntaxhighlight> |
|||
{{omit from|Batch File}} |
|||
=={{header|C}}== |
|||
Read/write raw device <code>/dev/dsp</code>. On Linux you need access to said device, meaning probably you should be in audio user group. |
|||
<syntaxhighlight 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; |
|||
}</syntaxhighlight> |
|||
=={{header|C++}}== |
|||
Uses Windows MCI |
|||
<syntaxhighlight 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; |
|||
} |
|||
</syntaxhighlight> |
|||
=={{header|ChucK}}== |
|||
<syntaxhighlight 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;</syntaxhighlight> |
|||
=={{header|Common Lisp}}== |
|||
{{trans|C}} |
|||
<syntaxhighlight 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)) |
|||
</syntaxhighlight> |
|||
=={{header|Diego}}== |
|||
This <code>funct</code>ion returns a <code>{wav}</code> variable recorded from a thing in the mist. It understands that the found <code>thing</code> 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. |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
This is the <code>instruct</code>ion version, where the thing keeps the recording. |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
=={{header|FreeBASIC}}== |
|||
<syntaxhighlight lang="vbnet">#define PI 4 * Atn(1) |
|||
' Constants for the audio format |
|||
Dim Shared As Integer SAMPLE_RATE = 44100 |
|||
Dim Shared As Integer BITS_PER_SAMPLE = 16 |
|||
Dim Shared As Integer NUM_CHANNELS = 1 |
|||
' Generates a sine wave |
|||
Sub generateSineWave(buffer() As Short, frequency As Double) |
|||
Dim As Double increment = 2.0 * PI * frequency / SAMPLE_RATE |
|||
Dim As Double x = 0.0 |
|||
For i As Integer = 0 To Ubound(buffer) |
|||
buffer(i) = (Sin(x) * 32767.0) |
|||
x += increment |
|||
Next i |
|||
End Sub |
|||
' Write the header of the .wav file |
|||
Sub writeWaveHeader(file As Integer, numSamples As Integer) |
|||
' Write the RIFF header |
|||
Print #file, "RIFF"; |
|||
Put #file, , numSamples * 2 + 36 ' File size |
|||
Print #file, "WAVE"; |
|||
Dim As Integer SB = 16, FA = 1 |
|||
' Write the fmt sub-block |
|||
Print #file, "fmt "; |
|||
Put #file, , SB ' Size of the fmt sub-block |
|||
Put #file, , FA ' Audio format (1 = PCM) |
|||
Put #file, , NUM_CHANNELS ' Number of channels |
|||
Put #file, , SAMPLE_RATE ' Sample rate |
|||
Put #file, , SAMPLE_RATE * NUM_CHANNELS * BITS_PER_SAMPLE / 8 ' Byte rate |
|||
Put #file, , NUM_CHANNELS * BITS_PER_SAMPLE / 8 ' Alineación de bloques |
|||
Put #file, , BITS_PER_SAMPLE ' Bits per sample |
|||
' Write the data sub-block |
|||
Print #file, "data"; |
|||
Put #file, , numSamples * 2 ' Data size |
|||
End Sub |
|||
Dim As Integer file = Freefile |
|||
Open "output.wav" For Binary As #file |
|||
' Generates a 440 Hz sine wave for 5 seconds |
|||
Dim As Integer numSamples = SAMPLE_RATE * 5 |
|||
Dim As Short buffer(numSamples - 1) |
|||
generateSineWave(buffer(), 440.0) |
|||
' Write the .wav file |
|||
writeWaveHeader(file, numSamples) |
|||
Put #file, , buffer() |
|||
Close #file</syntaxhighlight> |
|||
=={{header|Go}}== |
|||
{{works with|Ubuntu 16.04}} |
|||
<br> |
|||
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. |
|||
<syntaxhighlight 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.") |
|||
}</syntaxhighlight> |
|||
=={{header|GUISS}}== |
|||
Here we activate the Microsoft Windows '95 Sound Recorder: |
|||
<syntaxhighlight lang="guiss">Start,Programs,Accessories,Sound Recorder,Button:Record</syntaxhighlight> |
|||
=={{header|Java}}== |
|||
Java can record sound without external libraries. |
|||
<syntaxhighlight lang="java"> |
|||
import java.io.IOException; |
|||
import java.util.concurrent.Executors; |
|||
import java.util.concurrent.ScheduledExecutorService; |
|||
import java.util.concurrent.TimeUnit; |
|||
import java.io.File; |
|||
import javax.sound.sampled.AudioFileFormat.*; |
|||
public final class SoundRecorder { |
|||
public static void main(String[] args) { |
|||
SoundRecorder recorder = new SoundRecorder(); |
|||
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); |
|||
scheduler.schedule( () -> recorder.finish(), 10, TimeUnit.SECONDS); |
|||
scheduler.shutdown(); |
|||
recorder.start(); |
|||
} |
|||
private void start() { |
|||
try { |
|||
AudioFormat format = createAudioFormat(); |
|||
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); |
|||
if ( ! AudioSystem.isLineSupported(info) ) { |
|||
System.out.println("Data line format is not supported"); |
|||
Runtime.getRuntime().exit(0); |
|||
} |
|||
line = (TargetDataLine) AudioSystem.getLine(info); |
|||
line.open(format); |
|||
line.start(); |
|||
System.out.println("Starting to capture and record audio"); |
|||
AudioInputStream audioInputStream = new AudioInputStream(line); |
|||
AudioSystem.write(audioInputStream, audioFileType, wavFile); |
|||
} catch (LineUnavailableException | IOException exception) { |
|||
exception.printStackTrace(System.err); |
|||
} |
|||
} |
|||
private AudioFormat createAudioFormat() { |
|||
final float sampleRate = 16_000.0F; |
|||
final int sampleSizeInBits = 16; |
|||
final int channels = 1; |
|||
final boolean signed = true; |
|||
final boolean bigEndian = true; |
|||
// Monophonic 16-bit PCM audio format |
|||
return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian); |
|||
} |
|||
private void finish() { |
|||
line.stop(); |
|||
line.close(); |
|||
System.out.println("Finished capturing and recording audio"); |
|||
} |
|||
private TargetDataLine line; |
|||
private final File wavFile = new File("SoundRecorder.wav"); |
|||
private final AudioFileFormat.Type audioFileType = AudioFileFormat.Type.WAVE; |
|||
}</syntaxhighlight> |
|||
=={{header|Julia}}== |
|||
<syntaxhighlight lang="julia"> |
|||
using PortAudio, LibSndFile |
|||
stream = PortAudioStream("Microphone (USB Microphone)", 1, 0) # 44100 samples/sec |
|||
buf = read(stream, 441000) |
|||
save("recorded10sec.wav", buf) |
|||
</syntaxhighlight> |
|||
=={{header|Kotlin}}== |
|||
{{trans|Scala}} |
|||
<syntaxhighlight 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) |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|Liberty BASIC}}== |
|||
LB can easily send a MCI string to the OS, or extra routines eg SOX, so a minimal solution could be |
|||
<syntaxhighlight lang="lb"> |
|||
run "sndrec32.exe" |
|||
</syntaxhighlight> |
|||
A more direct way is.. |
|||
<syntaxhighlight 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 |
|||
</syntaxhighlight> |
|||
=={{header|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.<syntaxhighlight 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</syntaxhighlight> |
|||
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
|||
<syntaxhighlight lang="mathematica">SystemDialogInput["RecordSound"]</syntaxhighlight> |
|||
=={{header|Nim}}== |
|||
{{trans|Go}} |
|||
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. |
|||
<syntaxhighlight 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"</syntaxhighlight> |
|||
=={{header|OCaml}}== |
|||
{{trans|C}} |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
=={{header|Phix}}== |
|||
{{trans|BBC_BASIC}} |
|||
{{trans|C}} |
|||
{{trans|Go}} |
|||
<!--<syntaxhighlight lang="phix">(notonline)--> |
|||
<span style="color: #000080;font-style:italic;">-- |
|||
-- demo\rosetta\Record_sound.exw |
|||
-- ============================= |
|||
--</span> |
|||
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (file i/o)</span> |
|||
<span style="color: #008080;">constant</span> <span style="color: #000000;">wavfile</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"capture.wav"</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #000000;">bitspersample</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">16</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #000000;">channels</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #000000;">samplespersec</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">44100</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #000000;">alignment</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">bitspersample</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">channels</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #000000;">bytespersec</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">alignment</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">samplespersec</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #000000;">params</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">" bitspersample %d channels %d alignment %d samplespersec %d bytespersec %d"</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #0000FF;">{</span><span style="color: #000000;">bitspersample</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">channels</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">alignment</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">samplespersec</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">bytespersec</span><span style="color: #0000FF;">}),</span> |
|||
<span style="color: #000000;">error_size</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2048</span> |
|||
<span style="color: #004080;">atom</span> <span style="color: #000000;">winmm</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">NULL</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">xmciSendString</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pError</span> |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">mciSendString</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">msg</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">winmm</span><span style="color: #0000FF;">=</span><span style="color: #004600;">NULL</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">winmm</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">open_dll</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"winmm.dll"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">xmciSendString</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_c_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">winmm</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"mciSendStringA"</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #0000FF;">{</span><span style="color: #000000;">C_PTR</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- LPCTSTR lpszCommand</span> |
|||
<span style="color: #000000;">C_PTR</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- LPTSTR lpszReturnString</span> |
|||
<span style="color: #000000;">C_INT</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- UINT cchReturn</span> |
|||
<span style="color: #000000;">C_PTR</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- HANDLE hwndCallback</span> |
|||
<span style="color: #000000;">C_INT</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- MCIERROR</span> |
|||
<span style="color: #000000;">pError</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">error_size</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #004080;">atom</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">c_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xmciSendString</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pError</span><span style="color: #0000FF;">,</span><span style="color: #000000;">error_size</span><span style="color: #0000FF;">,</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"error %0x: %s"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">peek_string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pError</span><span style="color: #0000FF;">)})</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
<span style="color: #008080;">include</span> <span style="color: #000000;">get</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> <span style="color: #000080;font-style:italic;">-- get_bytes()</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">record</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">bytes</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">open</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"/dev/dsp"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"rb"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">fn</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008000;">""</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">get_bytes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bytes</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">play</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">buf</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">buf</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">open</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"/dev/dsp"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"wb"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">fn</span><span style="color: #0000FF;">!=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">buf</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">WINDOWS</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">mciSendString</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"close all"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">mciSendString</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"open new type waveaudio alias capture"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">mciSendString</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"set capture"</span> <span style="color: #0000FF;">&</span> <span style="color: #000000;">params</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Press SPACE to start recording..."</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">while</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()!=</span><span style="color: #008000;">' '</span> <span style="color: #008080;">do</span> <span style="color: #008080;">end</span> <span style="color: #008080;">while</span> |
|||
<span style="color: #000000;">mciSendString</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"record capture"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Recording, press SPACE to stop..."</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">while</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()!=</span><span style="color: #008000;">' '</span> <span style="color: #008080;">do</span> <span style="color: #008080;">end</span> <span style="color: #008080;">while</span> |
|||
<span style="color: #000000;">mciSendString</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"stop capture"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">mciSendString</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"save capture "</span> <span style="color: #0000FF;">&</span> <span style="color: #000000;">wavfile</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">mciSendString</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"delete capture"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">mciSendString</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"close capture"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Captured audio is stored in "</span><span style="color: #0000FF;">&</span><span style="color: #000000;">wavfile</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">LINUX</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000080;font-style:italic;">-- warning: untested</span> |
|||
<span style="color: #000000;">play</span><span style="color: #0000FF;">(</span><span style="color: #000000;">record</span><span style="color: #0000FF;">(</span><span style="color: #000000;">65536</span><span style="color: #0000FF;">))</span> |
|||
<span style="color: #000080;font-style:italic;">-- -- 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")</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<!--</syntaxhighlight>--> |
|||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
||
<lang PicoLisp>(in '(rec -q -c1 -tu16 - trim 0 2) # Record 2 seconds |
|||
<syntaxhighlight lang="picolisp">(in '(rec -q -c1 -tu16 - trim 0 2) # Record 2 seconds |
|||
(make |
(make |
||
(while (rd 2) |
(while (rd 2) |
||
(link @) ) ) )</ |
(link @) ) ) )</syntaxhighlight> |
||
Output: |
Output: |
||
<pre>-> (16767 19071 17279 ... 5503 9343 14719) # 96000 numbers</pre> |
<pre>-> (16767 19071 17279 ... 5503 9343 14719) # 96000 numbers</pre> |
||
=={{header|Python}}== |
=={{header|Python}}== |
||
<lang python>import pyaudio |
|||
<syntaxhighlight lang="python">import pyaudio |
|||
chunk = 1024 |
chunk = 1024 |
||
Line 28: | Line 807: | ||
data = stream.read(chunk) |
data = stream.read(chunk) |
||
print [ord(i) for i in data]</ |
print [ord(i) for i in data]</syntaxhighlight> |
||
=={{header|Racket}}== |
|||
{{trans|C}} |
|||
<syntaxhighlight 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)) |
|||
</syntaxhighlight> |
|||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
Slightly modified from an example provided with the <code>Audio::PortAudio</code> module distribution. |
|||
<syntaxhighlight lang="raku" line>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; |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|Scala}}== |
|||
{{libheader|Scala}} |
|||
<syntaxhighlight 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() |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
{{libheader|Snack}} |
{{libheader|Snack}}<syntaxhighlight lang="tcl">package require sound |
||
<lang tcl>package require sound |
|||
# Helper to do a responsive wait |
# Helper to do a responsive wait |
||
Line 50: | Line 964: | ||
# Destroy the recording object |
# Destroy the recording object |
||
$recording destroy</ |
$recording destroy</syntaxhighlight> |
||
=={{header|Wee Basic}}== |
|||
{{omit from|Brlcad}} |
|||
<syntaxhighlight lang="wee basic">print 1 "Recording..." |
|||
{{omit from|Openscad}} |
|||
micrec |
|||
{{omit from|Lotus 123 Macro Scripting}} |
|||
print 1 "Playing..." |
|||
micpla |
|||
end</syntaxhighlight> |
|||
=={{header|Wren}}== |
|||
{{trans|Go}} |
|||
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. |
|||
<syntaxhighlight lang="wren">/* 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.")</syntaxhighlight> |
|||
<br> |
|||
We now embed this in the following C program, compile and run it. |
|||
<syntaxhighlight 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) { |
|||
[[Category:Temporal media]] |
|||
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; |
|||
}</syntaxhighlight> |
Revision as of 16:25, 3 April 2024
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
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
BBC BASIC
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$
C
Read/write raw device /dev/dsp
. On Linux you need access to said device, meaning probably you should be in audio user group.
#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;
}
C++
Uses Windows MCI
#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;
}
ChucK
// 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;
Common 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))
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.
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
This is the instruct
ion version, where the thing keeps the recording.
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
FreeBASIC
#define PI 4 * Atn(1)
' Constants for the audio format
Dim Shared As Integer SAMPLE_RATE = 44100
Dim Shared As Integer BITS_PER_SAMPLE = 16
Dim Shared As Integer NUM_CHANNELS = 1
' Generates a sine wave
Sub generateSineWave(buffer() As Short, frequency As Double)
Dim As Double increment = 2.0 * PI * frequency / SAMPLE_RATE
Dim As Double x = 0.0
For i As Integer = 0 To Ubound(buffer)
buffer(i) = (Sin(x) * 32767.0)
x += increment
Next i
End Sub
' Write the header of the .wav file
Sub writeWaveHeader(file As Integer, numSamples As Integer)
' Write the RIFF header
Print #file, "RIFF";
Put #file, , numSamples * 2 + 36 ' File size
Print #file, "WAVE";
Dim As Integer SB = 16, FA = 1
' Write the fmt sub-block
Print #file, "fmt ";
Put #file, , SB ' Size of the fmt sub-block
Put #file, , FA ' Audio format (1 = PCM)
Put #file, , NUM_CHANNELS ' Number of channels
Put #file, , SAMPLE_RATE ' Sample rate
Put #file, , SAMPLE_RATE * NUM_CHANNELS * BITS_PER_SAMPLE / 8 ' Byte rate
Put #file, , NUM_CHANNELS * BITS_PER_SAMPLE / 8 ' Alineación de bloques
Put #file, , BITS_PER_SAMPLE ' Bits per sample
' Write the data sub-block
Print #file, "data";
Put #file, , numSamples * 2 ' Data size
End Sub
Dim As Integer file = Freefile
Open "output.wav" For Binary As #file
' Generates a 440 Hz sine wave for 5 seconds
Dim As Integer numSamples = SAMPLE_RATE * 5
Dim As Short buffer(numSamples - 1)
generateSineWave(buffer(), 440.0)
' Write the .wav file
writeWaveHeader(file, numSamples)
Put #file, , buffer()
Close #file
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.
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.")
}
GUISS
Here we activate the Microsoft Windows '95 Sound Recorder:
Start,Programs,Accessories,Sound Recorder,Button:Record
Java
Java can record sound without external libraries.
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.io.File;
import javax.sound.sampled.AudioFileFormat.*;
public final class SoundRecorder {
public static void main(String[] args) {
SoundRecorder recorder = new SoundRecorder();
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.schedule( () -> recorder.finish(), 10, TimeUnit.SECONDS);
scheduler.shutdown();
recorder.start();
}
private void start() {
try {
AudioFormat format = createAudioFormat();
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
if ( ! AudioSystem.isLineSupported(info) ) {
System.out.println("Data line format is not supported");
Runtime.getRuntime().exit(0);
}
line = (TargetDataLine) AudioSystem.getLine(info);
line.open(format);
line.start();
System.out.println("Starting to capture and record audio");
AudioInputStream audioInputStream = new AudioInputStream(line);
AudioSystem.write(audioInputStream, audioFileType, wavFile);
} catch (LineUnavailableException | IOException exception) {
exception.printStackTrace(System.err);
}
}
private AudioFormat createAudioFormat() {
final float sampleRate = 16_000.0F;
final int sampleSizeInBits = 16;
final int channels = 1;
final boolean signed = true;
final boolean bigEndian = true;
// Monophonic 16-bit PCM audio format
return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
}
private void finish() {
line.stop();
line.close();
System.out.println("Finished capturing and recording audio");
}
private TargetDataLine line;
private final File wavFile = new File("SoundRecorder.wav");
private final AudioFileFormat.Type audioFileType = AudioFileFormat.Type.WAVE;
}
Julia
using PortAudio, LibSndFile
stream = PortAudioStream("Microphone (USB Microphone)", 1, 0) # 44100 samples/sec
buf = read(stream, 441000)
save("recorded10sec.wav", buf)
Kotlin
// 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)
}
}
Liberty BASIC
LB can easily send a MCI string to the OS, or extra routines eg SOX, so a minimal solution could be
run "sndrec32.exe"
A more direct way is..
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
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.
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
Mathematica/Wolfram Language
SystemDialogInput["RecordSound"]
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.
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"
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
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
(in '(rec -q -c1 -tu16 - trim 0 2) # Record 2 seconds
(make
(while (rd 2)
(link @) ) ) )
Output:
-> (16767 19071 17279 ... 5503 9343 14719) # 96000 numbers
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]
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))
Raku
(formerly Perl 6)
Slightly modified from an example provided with the Audio::PortAudio
module distribution.
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;
}
}
}
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()
}
}
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
Wee Basic
print 1 "Recording..."
micrec
print 1 "Playing..."
micpla
end
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.
/* 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.")
We now embed this in the following C program, compile and run it.
#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;
}
- 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
- Diego
- FreeBASIC
- Go
- GUISS
- Java
- Julia
- Kotlin
- Liberty BASIC
- LiveCode
- Mathematica
- Wolfram Language
- Nim
- OCaml
- Phix
- PicoLisp
- Python
- Racket
- Raku
- Scala
- Tcl
- Snack
- Wee Basic
- Wren