Sine wave

From Rosetta Code
Sine wave is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.


Task

Generate a sine wave:

  1. you choose the frequency of the wave
  2. generate a sine wave for 5 seconds
  3. play sound


Go[edit]

Works with: Ubuntu 16.04


Go lacks audio support in its standard library and, whilst there are third party packages that could be used, an easier approach is to invoke the SoX utility's 'play' command as was done in the second Kotlin example.

package main
 
import (
"fmt"
"os/exec"
)
 
func main() {
synthType := "sine"
duration := "5"
frequency := "440"
cmd := exec.Command("play", "-n", "synth", duration, synthType, frequency)
err := cmd.Run()
if err != nil {
fmt.Println(err)
}
}

Kotlin[edit]

Using Java Sound API[edit]

// Version 1.2.41
 
import javax.sound.sampled.AudioFormat
import javax.sound.sampled.AudioSystem
import kotlin.math.sin
import kotlin.math.PI
 
fun sineWave(frequency: Int, seconds: Int, sampleRate: Int): ByteArray {
val samples = seconds * sampleRate
val result = ByteArray(samples)
val interval = sampleRate.toDouble() / frequency
for (i in 0 until samples) {
val angle = 2.0 * PI * i / interval
result[i] = (sin(angle) * 127).toByte()
}
return result
}
 
fun main(args: Array<String>) {
val sampleRate = 44000
val buffer = sineWave(440, 5, sampleRate)
val format = AudioFormat(sampleRate.toFloat(), 8, 1, true, true)
val line = AudioSystem.getSourceDataLine(format)
with (line) {
open(format)
start()
write(buffer, 0, buffer.size)
drain()
close()
}
}

Invoking SoX[edit]

An easier approach invoking the SoX utility's 'play' command which has this stuff built-in. The following was tested on Ubuntu 16.04.

// Version 1.2.41
 
fun main(args:Array<String>) {
val synthType = "sine"
val duration = "5"
val frequency = "440"
val pb = ProcessBuilder("play", "-n", "synth", duration, synthType, frequency)
pb.directory(null)
val proc = pb.start()
proc.waitFor()
}

Perl 6[edit]

Works with: Rakudo version 2018.04.01

What a horribly underspecified task. Ah well, gives me lots of wiggle room to cheat in various ways.

my ($rows,$cols) = qx/stty size/.words;
my $v = floor $rows / 2;
print "\e[H\e[J", 'Generating sine wave of zero amplitude and zero frequency for 5 seconds...',
"\e[$v;0H", '_' x $cols;
sleep 5;
say "\e[H\e[J", 'No?, ok how about this:';
 
use SVG;
my $filename = 'sine.svg';
my $out = open($filename, :w) orelse .die;
$out.say: SVG.serialize(
svg => [
width => 400, height => 150, style => 'stroke:rgb(0,0,255)',
:rect[:width<100%>, :height<100%>, :fill<white>],
:path[ :fill<none>, :d('M0,25 C36.42,25,63.58,125,100,125 M100,125 C136.42,125,163.58,25,200,25 M200,25 C236.42,25,263.58,125,300,125 M300,125 C336.42,125,363.58,25,400,25') ],
],
);
close $out;
say "Sine wave generated to {$filename.IO.absolute}, better open it quickly...";
sleep 5;
unlink $filename;
say 'Oops, too late.';
say 'Still no? Ok how about:';
shell 'play -n -c1 synth 5.0 sin %-12';

Phix[edit]

Windows only

atom k32=NULL, xBeep
 
procedure beep(integer frequency, duration=5000)
if platform()=WINDOWS then
if k32=NULL then
k32 = open_dll("kernel32.dll")
xBeep = define_c_proc(k32, "Beep", {C_INT,C_INT})
end if
c_proc(xBeep,{frequency,duration})
end if
end procedure
 
beep(prompt_number("Enter Frequency (100..10000 recommended):",{0x25,0x7FFF}))