1
1
/**
2
- * The sounds library provides functions for constructing and playing sounds.
2
+ * The `sound` module provides functions for constructing and playing sounds.
3
3
*
4
4
* A wave is a function that takes in a number `t` and returns
5
5
* a number representing the amplitude at time `t`.
6
6
* The amplitude should fall within the range of [-1, 1].
7
7
*
8
- * A Sound is a pair(wave, duration) where duration is the length of the sound in seconds.
8
+ * A Sound is a pair(wave, duration) where duration is the length of the Sound in seconds.
9
9
* The constructor make_sound and accessors get_wave and get_duration are provided.
10
10
*
11
11
* Sound Discipline:
12
- * For all sounds , the wave function applied to and time `t` beyond its duration returns 0, that is:
12
+ * For all Sounds , the wave function applied to and time `t` beyond its duration returns 0, that is:
13
13
* `(get_wave(sound))(get_duration(sound) + x) === 0` for any x >= 0.
14
14
*
15
15
* Two functions which combine Sounds, `consecutively` and `simultaneously` are given.
16
- * Additionally, we provide sound transformation functions `adsr` and `phase_mod`
16
+ * Additionally, we provide Sound transformation functions `adsr` and `phase_mod`
17
17
* which take in a Sound and return a Sound.
18
18
*
19
19
* Finally, the provided `play` function takes in a Sound and plays it using your
@@ -127,7 +127,7 @@ const recording_signal_ms = 100;
127
127
const pre_recording_signal_pause_ms = 200 ;
128
128
129
129
function play_recording_signal ( ) {
130
- play_concurrently ( sine_sound ( 1200 , recording_signal_ms / 1000 ) ) ;
130
+ play ( sine_sound ( 1200 , recording_signal_ms / 1000 ) ) ;
131
131
}
132
132
133
133
// eslint-disable-next-line @typescript-eslint/no-shadow
@@ -175,10 +175,11 @@ export function init_record(): string {
175
175
}
176
176
177
177
/**
178
- * takes a <CODE>buffer</CODE> duration (in seconds) as argument, and
178
+ * Records a sound until the returned stop function is called.
179
+ * Takes a <CODE>buffer</CODE> duration (in seconds) as argument, and
179
180
* returns a nullary stop function <CODE>stop</CODE>. A call
180
- * <CODE>stop()</CODE> returns a sound promise: a nullary function
181
- * that returns a sound . Example: <PRE><CODE>init_record();
181
+ * <CODE>stop()</CODE> returns a Sound promise: a nullary function
182
+ * that returns a Sound . Example: <PRE><CODE>init_record();
182
183
* const stop = record(0.5);
183
184
* // record after 0.5 seconds. Then in next query:
184
185
* const promise = stop();
@@ -188,7 +189,7 @@ export function init_record(): string {
188
189
* @param buffer - pause before recording, in seconds
189
190
* @returns nullary <CODE>stop</CODE> function;
190
191
* <CODE>stop()</CODE> stops the recording and
191
- * returns a sound promise: a nullary function that returns the recorded sound
192
+ * returns a Sound promise: a nullary function that returns the recorded Sound
192
193
*/
193
194
export function record ( buffer : number ) : ( ) => ( ) => Sound {
194
195
check_permission ( ) ;
@@ -213,15 +214,15 @@ export function record(buffer: number): () => () => Sound {
213
214
/**
214
215
* Records a sound of given <CODE>duration</CODE> in seconds, after
215
216
* a <CODE>buffer</CODE> also in seconds, and
216
- * returns a sound promise: a nullary function
217
- * that returns a sound . Example: <PRE><CODE>init_record();
217
+ * returns a Sound promise: a nullary function
218
+ * that returns a Sound . Example: <PRE><CODE>init_record();
218
219
* const promise = record_for(2, 0.5);
219
- * // In next query, you can play the promised sound , by
220
+ * // In next query, you can play the promised Sound , by
220
221
* // applying the promise:
221
222
* play(promise());</CODE></PRE>
222
223
* @param duration duration in seconds
223
224
* @param buffer pause before recording, in seconds
224
- * @return <CODE>promise</CODE>: nullary function which returns recorded sound
225
+ * @return <CODE>promise</CODE>: nullary function which returns recorded Sound
225
226
*/
226
227
export function record_for ( duration : number , buffer : number ) : ( ) => Sound {
227
228
recorded_sound = undefined ;
@@ -270,8 +271,8 @@ export function record_for(duration: number, buffer: number): () => Sound {
270
271
* that takes in a non-negative input time and returns an amplitude
271
272
* between -1 and 1.
272
273
*
273
- * @param wave wave function of the sound
274
- * @param duration duration of the sound
274
+ * @param wave wave function of the Sound
275
+ * @param duration duration of the Sound
275
276
* @return with wave as wave function and duration as duration
276
277
* @example const s = make_sound(t => Math_sin(2 * Math_PI * 440 * t), 5);
277
278
*/
@@ -319,33 +320,33 @@ export function is_sound(x: any): x is Sound {
319
320
/**
320
321
* Plays the given Wave using the computer’s sound device, for the duration
321
322
* given in seconds.
322
- * The sound is only played if no other sounds are currently being played.
323
323
*
324
324
* @param wave the wave function to play, starting at 0
325
- * @return the given sound
325
+ * @return the resulting Sound
326
326
* @example play_wave(t => math_sin(t * 3000), 5);
327
327
*/
328
- export function play_wave ( wave : Wave , duration : number ) : AudioPlayed {
328
+ export function play_wave ( wave : Wave , duration : number ) : Sound {
329
329
return play ( make_sound ( wave , duration ) ) ;
330
330
}
331
331
332
332
/**
333
333
* Plays the given Sound using the computer’s sound device.
334
- * The sound is only played if no other sounds are currently being played.
334
+ * The sound is added to a list of sounds to be played one-at-a-time
335
+ * in a Source Academy tab.
335
336
*
336
- * @param sound the sound to play
337
- * @return the given sound
338
- * @example play (sine_sound(440, 5));
337
+ * @param sound the Sound to play
338
+ * @return the given Sound
339
+ * @example play_in_tab (sine_sound(440, 5));
339
340
*/
340
- export function play ( sound : Sound ) : AudioPlayed {
341
+ export function play_in_tab ( sound : Sound ) : Sound {
341
342
// Type-check sound
342
343
if ( ! is_sound ( sound ) ) {
343
- throw new Error ( `${ play . name } is expecting sound, but encountered ${ sound } ` ) ;
344
+ throw new Error ( `${ play_in_tab . name } is expecting sound, but encountered ${ sound } ` ) ;
344
345
// If a sound is already playing, terminate execution.
345
346
} else if ( isPlaying ) {
346
- throw new Error ( `${ play . name } : audio system still playing previous sound` ) ;
347
+ throw new Error ( `${ play_in_tab . name } : audio system still playing previous sound` ) ;
347
348
} else if ( get_duration ( sound ) < 0 ) {
348
- throw new Error ( `${ play . name } : duration of sound is negative` ) ;
349
+ throw new Error ( `${ play_in_tab . name } : duration of sound is negative` ) ;
349
350
} else {
350
351
// Instantiate audio context if it has not been instantiated.
351
352
if ( ! audioplayer ) {
@@ -391,43 +392,31 @@ export function play(sound: Sound): AudioPlayed {
391
392
riffwave . header . bitsPerSample = 16 ;
392
393
riffwave . Make ( channel ) ;
393
394
394
- /*
395
- const audio = new Audio(riffwave.dataURI);
396
- const source2 = audioplayer.createMediaElementSource(audio);
397
- source2.connect(audioplayer.destination);
398
-
399
- // Connect data to output destination
400
- isPlaying = true;
401
- audio.play();
402
- audio.onended = () => {
403
- source2.disconnect(audioplayer.destination);
404
- isPlaying = false;
405
- }; */
406
-
407
395
const soundToPlay = {
408
396
toReplString : ( ) => '<AudioPlayed>' ,
409
397
dataUri : riffwave . dataURI ,
410
398
} ;
411
399
audioPlayed . push ( soundToPlay ) ;
412
- return soundToPlay ;
400
+ return sound ;
413
401
}
414
402
}
415
403
416
404
/**
417
405
* Plays the given Sound using the computer’s sound device
418
- * on top of any sounds that are currently playing.
406
+ * on top of any Sounds that are currently playing.
419
407
*
420
- * @param sound the sound to play
421
- * @example play_concurrently(sine_sound(440, 5));
408
+ * @param sound the Sound to play
409
+ * @return the given Sound
410
+ * @example play(sine_sound(440, 5));
422
411
*/
423
- export function play_concurrently ( sound : Sound ) : void {
412
+ export function play ( sound : Sound ) : Sound {
424
413
// Type-check sound
425
414
if ( ! is_sound ( sound ) ) {
426
415
throw new Error (
427
- `${ play_concurrently . name } is expecting sound, but encountered ${ sound } ` ,
416
+ `${ play . name } is expecting sound, but encountered ${ sound } ` ,
428
417
) ;
429
- } else if ( get_duration ( sound ) <= 0 ) {
430
- // Do nothing
418
+ } else if ( get_duration ( sound ) < 0 ) {
419
+ throw new Error ( ` ${ play . name } : duration of sound is negative` ) ;
431
420
} else {
432
421
// Instantiate audio context if it has not been instantiated.
433
422
if ( ! audioplayer ) {
@@ -475,6 +464,7 @@ export function play_concurrently(sound: Sound): void {
475
464
source . disconnect ( audioplayer . destination ) ;
476
465
isPlaying = false ;
477
466
} ;
467
+ return sound ;
478
468
}
479
469
}
480
470
@@ -489,45 +479,45 @@ export function stop(): void {
489
479
// Primitive sounds
490
480
491
481
/**
492
- * Makes a noise sound with given duration
482
+ * Makes a noise Sound with given duration
493
483
*
494
484
* @param duration the duration of the noise sound
495
- * @return resulting noise sound
485
+ * @return resulting noise Sound
496
486
* @example noise_sound(5);
497
487
*/
498
488
export function noise_sound ( duration : number ) : Sound {
499
489
return make_sound ( ( _t ) => Math . random ( ) * 2 - 1 , duration ) ;
500
490
}
501
491
502
492
/**
503
- * Makes a silence sound with given duration
493
+ * Makes a silence Sound with given duration
504
494
*
505
- * @param duration the duration of the silence sound
506
- * @return resulting silence sound
495
+ * @param duration the duration of the silence Sound
496
+ * @return resulting silence Sound
507
497
* @example silence_sound(5);
508
498
*/
509
499
export function silence_sound ( duration : number ) : Sound {
510
500
return make_sound ( ( _t ) => 0 , duration ) ;
511
501
}
512
502
513
503
/**
514
- * Makes a sine wave sound with given frequency and duration
504
+ * Makes a sine wave Sound with given frequency and duration
515
505
*
516
- * @param freq the frequency of the sine wave sound
517
- * @param duration the duration of the sine wave sound
518
- * @return resulting sine wave sound
506
+ * @param freq the frequency of the sine wave Sound
507
+ * @param duration the duration of the sine wave Sound
508
+ * @return resulting sine wave Sound
519
509
* @example sine_sound(440, 5);
520
510
*/
521
511
export function sine_sound ( freq : number , duration : number ) : Sound {
522
512
return make_sound ( ( t ) => Math . sin ( 2 * Math . PI * t * freq ) , duration ) ;
523
513
}
524
514
525
515
/**
526
- * Makes a square wave sound with given frequency and duration
516
+ * Makes a square wave Sound with given frequency and duration
527
517
*
528
- * @param freq the frequency of the square wave sound
529
- * @param duration the duration of the square wave sound
530
- * @return resulting square wave sound
518
+ * @param freq the frequency of the square wave Sound
519
+ * @param duration the duration of the square wave Sound
520
+ * @return resulting square wave Sound
531
521
* @example square_sound(440, 5);
532
522
*/
533
523
export function square_sound ( f : number , duration : number ) : Sound {
@@ -545,11 +535,11 @@ export function square_sound(f: number, duration: number): Sound {
545
535
}
546
536
547
537
/**
548
- * Makes a triangle wave sound with given frequency and duration
538
+ * Makes a triangle wave Sound with given frequency and duration
549
539
*
550
- * @param freq the frequency of the triangle wave sound
551
- * @param duration the duration of the triangle wave sound
552
- * @return resulting triangle wave sound
540
+ * @param freq the frequency of the triangle wave Sound
541
+ * @param duration the duration of the triangle wave Sound
542
+ * @return resulting triangle wave Sound
553
543
* @example triangle_sound(440, 5);
554
544
*/
555
545
export function triangle_sound ( freq : number , duration : number ) : Sound {
@@ -569,11 +559,11 @@ export function triangle_sound(freq: number, duration: number): Sound {
569
559
}
570
560
571
561
/**
572
- * Makes a sawtooth wave sound with given frequency and duration
562
+ * Makes a sawtooth wave Sound with given frequency and duration
573
563
*
574
- * @param freq the frequency of the sawtooth wave sound
575
- * @param duration the duration of the sawtooth wave sound
576
- * @return resulting sawtooth wave sound
564
+ * @param freq the frequency of the sawtooth wave Sound
565
+ * @param duration the duration of the sawtooth wave Sound
566
+ * @return resulting sawtooth wave Sound
577
567
* @example sawtooth_sound(440, 5);
578
568
*/
579
569
export function sawtooth_sound ( freq : number , duration : number ) : Sound {
@@ -594,11 +584,11 @@ export function sawtooth_sound(freq: number, duration: number): Sound {
594
584
595
585
/**
596
586
* Makes a new Sound by combining the sounds in a given list
597
- * where the second sound is appended to the end of the first sound ,
598
- * the third sound is appended to the end of the second sound , and
599
- * so on. The effect is that the sounds in the list are joined end-to-end
587
+ * where the second Sound is appended to the end of the first Sound ,
588
+ * the third Sound is appended to the end of the second Sound , and
589
+ * so on. The effect is that the Sounds in the list are joined end-to-end
600
590
*
601
- * @param list_of_sounds given list of sounds
591
+ * @param list_of_sounds given list of Sounds
602
592
* @return the combined Sound
603
593
* @example consecutively(list(sine_sound(200, 2), sine_sound(400, 3)));
604
594
*/
@@ -615,10 +605,10 @@ export function consecutively(list_of_sounds: List): Sound {
615
605
}
616
606
617
607
/**
618
- * Makes a new Sound by combining the sounds in a given list
619
- * where all the sounds are overlapped on top of each other.
608
+ * Makes a new Sound by combining the Sounds in a given list
609
+ * where all the Sounds are overlapped on top of each other.
620
610
*
621
- * @param list_of_sounds given list of sounds
611
+ * @param list_of_sounds given list of Sounds
622
612
* @return the combined Sound
623
613
* @example simultaneously(list(sine_sound(200, 2), sine_sound(400, 3)))
624
614
*/
@@ -730,15 +720,15 @@ export function stacking_adsr(
730
720
}
731
721
732
722
/**
733
- * Returns a SoundTransformer which uses its argument
723
+ * Returns a Sound transformer which uses its argument
734
724
* to modulate the phase of a (carrier) sine wave
735
725
* of given frequency and duration with a given Sound.
736
726
* Modulating with a low frequency Sound results in a vibrato effect.
737
727
* Modulating with a Sound with frequencies comparable to
738
728
* the sine wave frequency results in more complex wave forms.
739
729
*
740
730
* @param freq the frequency of the sine wave to be modulated
741
- * @param duration the duration of the output soud
731
+ * @param duration the duration of the output Sound
742
732
* @param amount the amount of modulation to apply to the carrier sine wave
743
733
* @return function which takes in a Sound and returns a Sound
744
734
* @example phase_mod(440, 5, 1)(sine_sound(220, 5));
0 commit comments