Skip to content

Commit

Permalink
#16 added a sounds example
Browse files Browse the repository at this point in the history
  • Loading branch information
j50n committed Feb 13, 2022
1 parent 5cabb6e commit 841b9f3
Show file tree
Hide file tree
Showing 8 changed files with 296 additions and 2 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ deno doc --reload https://deno.land/x/proc/mod.ts 2> /dev/null
## Examples

- [Simple Examples for Input and Output Handlers](./runners/handlers/README.md)
- [Count Unique Words in _War and Peace_](./examples/warandpeace/README.md)
- [Playing Sounds with `aplay`](./examples/sounds/README.md)
- [Count the Unique Words in _War and Peace_](./examples/warandpeace/README.md)
- [Use `PushIterable` to Implement Workers](./examples/pushiterable/README.md)

## Related Projects
Expand Down
4 changes: 4 additions & 0 deletions build
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ cd "$HERE/examples/warandpeace" && (

cd "$HERE/examples/pushiterable" && (
PATH=".:$PATH" ./example-of-pushiterable.ts
)

cd "$HERE/examples/sounds" && (
./sounds.ts
)
3 changes: 3 additions & 0 deletions examples/pushiterable/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Use `PushIterable` to Implement Workers

This example takes a fundamentally different approach to running child
processes, flipping the direction of the data on the input (`stdin`) side.

`proc` can be used to manage persistent child processes that accept messages
from your parent process and respond back with messages of their own. In order
to "push" messages to a process, you need to use a
Expand Down
19 changes: 19 additions & 0 deletions examples/sounds/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Playing Sounds with `aplay`

Did you ever wonder if there were an easy way to play sounds in Deno?

Deno does not yet support the Web Audio API, so our ability to play sounds
natively is limited. Fortunately, `aplay` is available (at least on Ubuntu)
without requiring an install.

Programs that are written in `C`, like `aplay`, start up very quickly and run
efficiently. You can play a sound - or even multiple sounds at the same time -
without missing a beat. The example demonstrates this. The one caveat is IO
speed - if you are loading sounds from something other than memory. The example
downloads the sounds it will need into memory first, before it attempts to play
them. The WAV files are streamed through `stdin` to `aplay` using buffered,
non-blocking IO.

Have fun!

[sounds.ts](./sounds.ts)
49 changes: 49 additions & 0 deletions examples/sounds/sounds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env -S deno run --allow-run=aplay --allow-net=github.com,raw.githubusercontent.com

import * as proc from "../../mod.ts";

/**
* Grab the sound files from my github repository.
* @param name The name of the sound.
* @returns The WAV file.
*/
async function getSoundFile(name: string): Promise<Uint8Array> {
const url =
`https://github.com/j50n/deno-proc/blob/main/examples/sounds/${name}.wav?raw=true`;
return new Uint8Array(await (await fetch(url)).arrayBuffer());
}

/**
* Play a sound using `aplay`.
* @param sound A WAV file.
*/
async function play(sound: Uint8Array): Promise<void> {
for await (
const line of proc.runner(
proc.bytesInput(),
proc.stringIterableUnbufferedOutput(),
)().run({ cmd: ["aplay"] }, sound)
) {
console.log(line);
}
}

const [cowWav, cowbellWav] = await Promise.all([
getSoundFile("cow"),
getSoundFile("cowbell"),
]);

console.log(`MOO sound is ${cowWav.length} bytes.`);
console.log(`Bell sound is ${cowbellWav.length} bytes.`);

/* Moo. */
await play(cowWav);
await proc.sleep(100);

/* Ring a bell. */
await play(cowbellWav);
await proc.sleep(100);

/* Moo and ring a bell. */
await Promise.all([play(cowWav), play(cowbellWav)]);
await proc.sleep(100);
4 changes: 3 additions & 1 deletion examples/warandpeace/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Count Unique Words in _War and Peace_
# Count the Unique Words in _War and Peace_

This is a fun little example of line-oriented data processing.

Tolstoy's _War and Peace_ is sprawling and immense, and it uses a lot of words.
But how many _unique_ words does it contain?
Expand Down
212 changes: 212 additions & 0 deletions oundsUrl(name: string): string{
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
APLAY(1) General Commands Manual APLAY(1)

NNAAMMEE
arecord, aplay - command-line sound recorder and player for ALSA soundcard driver

SSYYNNOOPPSSIISS
aarreeccoorrdd [_f_l_a_g_s] [filename]
aappllaayy [_f_l_a_g_s] [filename [filename]] ...

DDEESSCCRRIIPPTTIIOONN
aarreeccoorrdd is a command-line soundfile recorder for the ALSA soundcard driver. It supports several file formats and multiple
soundcards with multiple devices. If recording with interleaved mode samples the file is automatically split before the
2GB filesize.

aappllaayy is much the same, only it plays instead of recording. For supported soundfile formats, the sampling rate, bit depth,
and so forth can be automatically determined from the soundfile header.

If filename is not specified, the standard output or input is used. The aappllaayy utility accepts multiple filenames.

OOPPTTIIOONNSS
_-_h_, _-_-_h_e_l_p
Help: show syntax.

_-_-_v_e_r_s_i_o_n
Print current version.

_-_l_, _-_-_l_i_s_t_-_d_e_v_i_c_e_s
List all soundcards and digital audio devices

_-_L_, _-_-_l_i_s_t_-_p_c_m_s
List all PCMs defined

_-_D_, _-_-_d_e_v_i_c_e_=_N_A_M_E
Select PCM by name

_-_q _-_-_q_u_i_e_t
Quiet mode. Suppress messages (not sound :))

_-_t_, _-_-_f_i_l_e_-_t_y_p_e _T_Y_P_E
File type (voc, wav, raw or au). If this parameter is omitted the WAVE format is used.

_-_c_, _-_-_c_h_a_n_n_e_l_s_=_#
The number of channels. The default is one channel. Valid values are 1 through 32.

_-_f _-_-_f_o_r_m_a_t_=_F_O_R_M_A_T
Sample format
Recognized sample formats are: S8 U8 S16_LE S16_BE U16_LE U16_BE S24_LE S24_BE U24_LE U24_BE S32_LE S32_BE U32_LE
U32_BE FLOAT_LE FLOAT_BE FLOAT64_LE FLOAT64_BE IEC958_SUBFRAME_LE IEC958_SUBFRAME_BE MU_LAW A_LAW IMA_ADPCM MPEG
GSM SPECIAL S24_3LE S24_3BE U24_3LE U24_3BE S20_3LE S20_3BE U20_3LE U20_3BE S18_3LE S18_3BE U18_3LE
Some of these may not be available on selected hardware
The available format shortcuts are:
-f cd (16 bit little endian, 44100, stereo) [-f S16_LE -c2 -r44100]
-f cdr (16 bit big endian, 44100, stereo) [-f S16_BE -c2 -f44100]
-f dat (16 bit little endian, 48000, stereo) [-f S16_LE -c2 -r48000]
If no format is given U8 is used.

_-_r_, _-_-_r_a_t_e_=_#_<_H_z_>
Sampling rate in Hertz. The default rate is 8000 Hertz. If the value specified is less than 300, it is taken as
the rate in kilohertz. Valid values are 2000 through 192000 Hertz.

_-_d_, _-_-_d_u_r_a_t_i_o_n_=_#
Interrupt after # seconds. A value of zero means infinity. The default is zero, so if this option is omitted then
the record/playback process will run until it is killed. Either '-d' or '-s' option is available exclusively.

_-_s_, _-_-_s_a_m_p_l_e_s_=_#
Interrupt after tranmission of # PCM frames. A value of zero means infinity. The default is zero, so if this op‐
tions is omitted then the record/playback process will run until it is killed. Either '-d' or '-s' option is
available exclusively.

_-_M_, _-_-_m_m_a_p
Use memory-mapped (mmap) I/O mode for the audio stream. If this option is not set, the read/write I/O mode will be
used.

_-_N_, _-_-_n_o_n_b_l_o_c_k
Open the audio device in non-blocking mode. If the device is busy the program will exit immediately. If this op‐
tion is not set the program will block until the audio device is available again.

_-_F_, _-_-_p_e_r_i_o_d_-_t_i_m_e_=_#
Distance between interrupts is # microseconds. If no period time and no period size is given then a quarter of the
buffer time is set.

_-_B_, _-_-_b_u_f_f_e_r_-_t_i_m_e_=_#
Buffer duration is # microseconds If no buffer time and no buffer size is given then the maximal allowed buffer
time but not more than 500ms is set.

_-_-_p_e_r_i_o_d_-_s_i_z_e_=_#
Distance between interrupts is # frames If no period size and no period time is given then a quarter of the buffer
size is set.

_-_-_b_u_f_f_e_r_-_s_i_z_e_=_#
Buffer duration is # frames If no buffer time and no buffer size is given then the maximal allowed buffer time but
not more than 500ms is set.

_-_A_, _-_-_a_v_a_i_l_-_m_i_n_=_#
Min available space for wakeup is # microseconds

_-_R_, _-_-_s_t_a_r_t_-_d_e_l_a_y_=_#
Delay for automatic PCM start is # microseconds (relative to buffer size if <= 0)

_-_T_, _-_-_s_t_o_p_-_d_e_l_a_y_=_#
Delay for automatic PCM stop is # microseconds from xrun

_-_v_, _-_-_v_e_r_b_o_s_e
Show PCM structure and setup. This option is accumulative. The VU meter is displayed when this is given twice or
three times.

_-_V_, _-_-_v_u_m_e_t_e_r_=_T_Y_P_E
Specifies the VU-meter type, either _s_t_e_r_e_o or _m_o_n_o. The stereo VU-meter is available only for 2-channel stereo
samples with interleaved format.

_-_I_, _-_-_s_e_p_a_r_a_t_e_-_c_h_a_n_n_e_l_s
One file for each channel. This option disables max-file-time and use-strftime, and ignores SIGUSR1. The stereo
VU meter is not available with separate channels.

_-_P Playback. This is the default if the program is invoked by typing aplay.

_-_C Record. This is the default if the program is invoked by typing arecord.

_-_i_, _-_-_i_n_t_e_r_a_c_t_i_v_e
Allow interactive operation via stdin. Currently only pause/resume via space or enter key is implemented.

_-_m_, _-_-_c_h_m_a_p_=_c_h_1_,_c_h_2_,_._._.
Give the channel map to override or follow. Pass channel position strings like _F_L, _F_R, etc.

If a device supports the override of the channel map, aappllaayy tries to pass the given channel map. If it doesn't
support the channel map override but still it provides the channel map information, aappllaayy tries to rearrange the
channel order in the buffer to match with the returned channel map from the device.

_-_-_d_i_s_a_b_l_e_-_r_e_s_a_m_p_l_e
Disable automatic rate resample.

_-_-_d_i_s_a_b_l_e_-_c_h_a_n_n_e_l_s
Disable automatic channel conversions.

_-_-_d_i_s_a_b_l_e_-_f_o_r_m_a_t
Disable automatic format conversions.

_-_-_d_i_s_a_b_l_e_-_s_o_f_t_v_o_l
Disable software volume control (softvol).

_-_-_t_e_s_t_-_p_o_s_i_t_i_o_n
Test ring buffer position.

_-_-_t_e_s_t_-_c_o_e_f_=_<_c_o_e_f_>
Test coefficient for ring buffer position; default is 8. Expression for validation is: coef * (buffer_size / 2).
Minimum value is 1.

_-_-_t_e_s_t_-_n_o_w_a_i_t
Do not wait for the ring buffer ‐ eats the whole CPU.

_-_-_m_a_x_-_f_i_l_e_-_t_i_m_e
While recording, when the output file has been accumulating sound for this long, close it and open a new output
file. Default is the maximum size supported by the file format: 2 GiB for WAV files. This option has no effect if
--separate-channels is specified.

_-_-_p_r_o_c_e_s_s_-_i_d_-_f_i_l_e _<_f_i_l_e _n_a_m_e_>
aplay writes its process ID here, so other programs can send signals to it.

_-_-_u_s_e_-_s_t_r_f_t_i_m_e
When recording, interpret %-codes in the file name parameter using the strftime facility whenever the output file
is opened. The important strftime codes are: %Y is the year, %m month, %d day of the month, %H hour, %M minute and
%S second. In addition, %v is the file number, starting at 1. When this option is specified, intermediate direc‐
tories for the output file are created automatically. This option has no effect if --separate-channels is speci‐
fied.

_-_-_d_u_m_p_-_h_w_-_p_a_r_a_m_s
Dump hw_params of the device preconfigured status to stderr. The dump lists capabilities of the selected device
such as supported formats, sampling rates, numbers of channels, period and buffer bytes/sizes/times. For raw de‐
vice hw:X this option basically lists hardware capabilities of the soundcard.

_-_-_f_a_t_a_l_-_e_r_r_o_r_s
Disables recovery attempts when errors (e.g. xrun) are encountered; the aplay process instead aborts immediately.

SSIIGGNNAALLSS
When recording, SIGINT, SIGTERM and SIGABRT will close the output file and exit. SIGUSR1 will close the output file, open
a new one, and continue recording. However, SIGUSR1 does not work with --separate-channels.

EEXXAAMMPPLLEESS
aappllaayy --cc 11 --tt rraaww --rr 2222005500 --ff mmuu__llaaww ffoooobbaarr
will play the raw file "foobar" as a 22050-Hz, mono, 8-bit, Mu-Law .au file.

aarreeccoorrdd --dd 1100 --ff ccdd --tt wwaavv --DD ccooppyy ffoooobbaarr..wwaavv
will record foobar.wav as a 10-second, CD-quality wave file, using the PCM "copy" (which might be defined in the
user's .asoundrc file as:
pcm.copy {
type plug
slave {
pcm hw
}
route_policy copy
}

aarreeccoorrdd --tt wwaavv ----mmaaxx--ffiillee--ttiimmee 3300 mmoonn..wwaavv
Record from the default audio source in monaural, 8,000 samples per second, 8 bits per sample. Start a new file
every 30 seconds. File names are mon-nn.wav, where nn increases from 01. The file after mon-99.wav is
mon-100.wav.

aarreeccoorrdd --ff ccdd --tt wwaavv ----mmaaxx--ffiillee--ttiimmee 33660000 ----uussee--ssttrrffttiimmee %%YY//%%mm//%%dd//lliisstteenn--%%HH--%%MM--%%vv..wwaavv
Record in stereo from the default audio source. Create a new file every hour. The files are placed in directories
based on their start dates and have names which include their start times and file numbers.

SSEEEE AALLSSOO
aallssaammiixxeerr((11)),, aammiixxeerr((11))

BBUUGGSS
Note that .aiff files are not currently supported.

AAUUTTHHOORR
aarreeccoorrdd and aappllaayy are by Jaroslav Kysela <[email protected]> This document is by Paul Winkler <[email protected]>. Updated
for Alsa 0.9 by James Tappin <[email protected]>

1 January 2010 APLAY(1)
4 changes: 4 additions & 0 deletions release-notes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Release Notes

## 0.14.1

- `#16` **documentation** Demonstrate using `aplay` to play `.wav` files.

## 0.14.0

- **feature** Support workers with `PushIterable`; includes example.
Expand Down

0 comments on commit 841b9f3

Please sign in to comment.