Waveform analysis/Doh ray me: Difference between revisions

m
(added Raku programming solution)
m (→‎{{header|Wren}}: Minor tidy)
 
(9 intermediate revisions by 8 users not shown)
Line 14:
 
Some optional aspects of the task have been ignored as they are not relevant to this particular example.
<langsyntaxhighlight lang="go">package main
 
import (
Line 93:
aav := sum / float64(len(freqs))
fmt.Printf("Actual average frequency = %.1f Hz (%s)\n", aav, getNote(aav))
}</langsyntaxhighlight>
 
{{out}}
Line 106:
=={{header|Julia}}==
Uses the LibSndFile library for WAV file reading and the DSP module's implementation of the ESPRIT algorithm to analyze the sound for its fundamental frequency.
<langsyntaxhighlight lang="julia">using DSP, FileIO, LibSndFile
 
const soundfilename = "Cscale3octaves.wav"
Line 175:
println(makenotelist(soundfilename))
 
</langsyntaxhighlight>{{out}}
<pre>
["DOH", "RAY", "MEE", "FAH", "SOH", "LAH", "TEE", "Doh", "Ray", "Mee", "Fah", "Soh", "Lah", "Lah", "Tee", "doh", "ray", "mee", "fah", "soh", "lah", "tee"]
</pre>
 
=={{header|Nim}}==
{{trans|Go}}
The input .wav file (notes.wav) is created by the [[https://rosettacode.org/wiki/Musical_scale#Nim Musical Scale#Nim]] entry.
 
<syntaxhighlight lang="nim">import endians, math, stats, strformat
 
const
Freqs = [261.6, 293.6, 329.6, 349.2, 392.0, 440.0, 493.9, 523.3]
Notes = ["Doh", "Ray", "Mee", "Fah", "Soh", "Lah", "Tee", "doh"]
 
 
func getNote(freq: float): string =
var index = Freqs.len
for i, f in Freqs:
if freq <= f:
index = i
break
result = if index == 0:
"Doh-"
elif index == Freqs.len:
"doh+"
elif Freqs[index] - freq <= freq - Freqs[index-1]:
Notes[index] & '-'
else:
Notes[index-1] & '+'
 
 
proc getUint32(buffer: openArray[byte]; pos: Natural): uint32 =
littleEndian32(result.addr, buffer[pos].unsafeAddr)
 
 
let file = open("notes.wav")
var hdr: array[44, byte]
let n = file.readBytes(hdr, 0, hdr.len)
doAssert n == hdr.len
 
# Check header parameters.
let sampleRate = hdr.getUint32(24)
echo "Sample rate: ", sampleRate
let dataLength = hdr.getUint32(40)
let duration = dataLength div sampleRate
echo "Duration: ", duration
 
var sum = 0.0
let sampleRateF = float(sampleRate)
var data = newSeq[byte](sampleRate)
let nbytes = 20
echo "Bytes examined: ", nbytes, " per sample"
for j in 0..<duration:
let n = file.readBytes(data, 0, data.len)
doAssert n == data.len
for i in 1..nbytes:
let bf = float(data[i]) / 32
let freq = arcsin(bf) * sampleRateF / (i.toFloat * 2 * Pi)
sum += freq
let cav = sum / float(duration.int * nbytes)
echo &"\nComputed average frequency = {cav:.1f} Hz ({cav.getNote()})"
 
let aav = mean(Freqs)
echo &"Actual average frequency = {aav:.1f} Hz ({aav.getNote()})"</syntaxhighlight>
 
{{out}}
<pre>Sample rate: 44100
Duration: 8
Bytes examined: 20 per sample
 
Computed average frequency = 387.1 Hz (Soh-)
Actual average frequency = 385.4 Hz (Soh-)</pre>
 
file.close()
 
=={{header|Perl}}==
The input .wav file (notes.wav) is created by the [[https://rosettacode.org/wiki/Musical_scale#Go Musical Scale#Go]] entry.
{{trans|Raku}}
<syntaxhighlight lang="perl"># 20200808 added Perl programming solution
 
use v5.10;
use strict;
use warnings;
use autodie;
 
use Math::Trig;
use List::Util qw/sum/;
use constant PI => 4 * atan2(1, 1);
 
my @freqs = qw ( 261.6 293.6 329.6 349.2 392.0 440.0 493.9 523.3 );
my @notes = qw ( Doh Ray Mee Fah Soh Lah Tee doh );
 
sub getNote {
my $freq = $_[0];
my $index = @freqs;
for (0..$index-1) { $index = $_ and last if $freq <= $freqs[$_] }
given ($index) {
when (0) { "Doh-" }
when (@freqs) { "doh+" }
default { $freqs[$index] - $freq <= $freq - $freqs[$index-1]
? $notes[$index] . "-" : $notes[$index-1] . "+" }
}
}
 
 
open my $fh, '<:raw', './notes.wav';
 
# http://www.topherlee.com/software/pcm-tut-wavformat.html
 
read $fh, my $header, 28;
print "Sample Rate : ", my $sampleRate = unpack(' x24 L< ', $header), "\n" ;
 
read $fh, $header, 16;
my $dataLength = unpack(' x12 L< ', $header);
print "Duration : ", my $duration = $dataLength / $sampleRate, "\n";
 
my ( $sum, $nbytes ) = ( 0, 20 ) ;
 
print "Bytes examined : $nbytes per sample\n";
 
while ( read $fh, my $data, $sampleRate ) {
my @chunk = split('', $data);
for my $k (1..$nbytes) {
my $bf = ord($chunk[$k]) / 32;
$sum += asin($bf) * $sampleRate / ( 2 * PI * $k );
}
}
 
close $fh;
 
my $cav = $sum / ( $duration * $nbytes );
printf "Computed average frequency = %.1f", $cav;
print " Hz (",getNote($cav),")\n";
 
my $aav = sum(@freqs) / @freqs;
printf "Actual average frequency = %.1f", $aav;
print " Hz (",getNote($aav),")\n";
</syntaxhighlight>
{{out}}
<pre>go run Musical_scale.go
file notes.wav
notes.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 8 bit, mono 44100 Hz
./Doh_ray_me.pl
Sample Rate : 44100
Duration : 8
Bytes examined : 20 per sample
Computed average frequency = 387.1 Hz (Soh-)
Actual average frequency = 385.4 Hz (Soh-)
</pre>
 
Line 183 ⟶ 329:
{{trans|Go}}
Likewise analyses the output file of [[Musical_scale#Phix]]
<!--<syntaxhighlight lang="phix">(notonline)-->
<lang Phix>constant freqs = {261.6, 293.6, 329.6, 349.2, 392.0, 440.0, 493.9, 523.3},
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (file i/o)</span>
notes = {"Doh", "Ray", "Mee", "Fah", "Soh", "Lah", "Tee", "doh"}
<span style="color: #008080;">constant</span> <span style="color: #000000;">freqs</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">261.6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">293.6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">329.6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">349.2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">392.0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">440.0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">493.9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">523.3</span><span style="color: #0000FF;">},</span>
<span style="color: #000000;">notes</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"Doh"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Ray"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Mee"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Fah"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Soh"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Lah"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Tee"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"doh"</span><span style="color: #0000FF;">}</span>
function getNote(atom freq)
integer idx = length(freqs)+1
<span style="color: #008080;">function</span> <span style="color: #000000;">getNote</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">freq</span><span style="color: #0000FF;">)</span>
for i=1 to length(freqs) do
<span style="color: #004080;">integer</span> <span style="color: #000000;">idx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">freqs</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span>
if freq<=freqs[i] then
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">freqs</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
idx = i
<span style="color: #008080;">if</span> <span style="color: #000000;">freq</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">freqs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
exit
<span style="color: #000000;">idx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
end if
<span style="color: #008080;">exit</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
string res
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
if idx=1 then
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span>
res = "Doh-"
<span style="color: #008080;">if</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
elsif idx>length(freqs) then
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"Doh-"</span>
res = "doh+"
<span style="color: #008080;">elsif</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">freqs</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
elsif freqs[idx]-freq <= freq-freqs[idx-1] then
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"doh+"</span>
res = notes[idx] & "-"
<span style="color: #008080;">elsif</span> <span style="color: #000000;">freqs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">]-</span><span style="color: #000000;">freq</span> <span style="color: #0000FF;"><=</span> <span style="color: #000000;">freq</span><span style="color: #0000FF;">-</span><span style="color: #000000;">freqs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
else
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">notes</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">&</span> <span style="color: #008000;">"-"</span>
res = notes[idx-1] & "+"
<span style="color: #008080;">else</span>
end if
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">notes</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">&</span> <span style="color: #008000;">"+"</span>
return res
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
object data = get_text("notes.wav")
if data=-1 then crash("error opening notes.wav") end if
<span style="color: #004080;">object</span> <span style="color: #000000;">data</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">get_text</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"notes.wav"</span><span style="color: #0000FF;">)</span>
integer sampleRate = bytes_to_int(data[25..28]),
<span style="color: #008080;">if</span> <span style="color: #000000;">data</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"error opening notes.wav"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
dataLength = bytes_to_int(data[41..44]),
<span style="color: #004080;">integer</span> <span style="color: #000000;">sampleRate</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">bytes_to_int</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">[</span><span style="color: #000000;">25</span><span style="color: #0000FF;">..</span><span style="color: #000000;">28</span><span style="color: #0000FF;">]),</span>
nbytes = 20, offset = 45
<span style="color: #000000;">dataLength</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">bytes_to_int</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">[</span><span style="color: #000000;">41</span><span style="color: #0000FF;">..</span><span style="color: #000000;">44</span><span style="color: #0000FF;">]),</span>
atom duration = dataLength/sampleRate,
<span style="color: #000000;">nbytes</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">20</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">offset</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">45</span>
tot = 0
<span style="color: #004080;">atom</span> <span style="color: #000000;">duration</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dataLength</span><span style="color: #0000FF;">/</span><span style="color: #000000;">sampleRate</span><span style="color: #0000FF;">,</span>
printf(1,"Sample Rate : %d\n", sampleRate)
<span style="color: #000000;">tot</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
printf(1,"Duration : %s\n", elapsed(duration))
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Sample Rate : %d\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">sampleRate</span><span style="color: #0000FF;">)</span>
printf(1,"Bytes examined : %d per sample\n\n", nbytes)
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Duration : %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">duration</span><span style="color: #0000FF;">))</span>
for j=1 to duration do
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Bytes examined : %d per sample\n\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nbytes</span><span style="color: #0000FF;">)</span>
for i=1 to nbytes do
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">duration</span> <span style="color: #008080;">do</span>
atom bf = data[offset+i]/32,
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">nbytes</span> <span style="color: #008080;">do</span>
freq = arcsin(bf) * sampleRate / (i*PI*2)
<span style="color: #004080;">atom</span> <span style="color: #000000;">bf</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">data</span><span style="color: #0000FF;">[</span><span style="color: #000000;">offset</span><span style="color: #0000FF;">+</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]/</span><span style="color: #000000;">32</span><span style="color: #0000FF;">,</span>
tot += freq
<span style="color: #000000;">freq</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">arcsin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bf</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">sampleRate</span> <span style="color: #0000FF;">/</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">*</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #000000;">tot</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">freq</span>
offset += sampleRate
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<span style="color: #000000;">offset</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">sampleRate</span>
atom cav = tot / (duration * nbytes),
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
aav = sum(freqs) / length(freqs)
<span style="color: #004080;">atom</span> <span style="color: #000000;">cav</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tot</span> <span style="color: #0000FF;">/</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">duration</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">nbytes</span><span style="color: #0000FF;">),</span>
printf(1,"Computed average frequency = %.1f Hz (%s)\n", {cav, getNote(cav)})
<span style="color: #000000;">aav</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sum</span><span style="color: #0000FF;">(</span><span style="color: #000000;">freqs</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">/</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">freqs</span><span style="color: #0000FF;">)</span>
printf(1,"Actual average frequency = %.1f Hz (%s)\n", {aav, getNote(aav)})</lang>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Computed average frequency = %.1f Hz (%s)\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">cav</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">getNote</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cav</span><span style="color: #0000FF;">)})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Actual average frequency = %.1f Hz (%s)\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">aav</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">getNote</span><span style="color: #0000FF;">(</span><span style="color: #000000;">aav</span><span style="color: #0000FF;">)})</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 242 ⟶ 391:
The input .wav file (notes.wav) is created by the [[https://rosettacode.org/wiki/Musical_scale#Go Musical Scale#Go]] entry.
{{trans|Go}}
<syntaxhighlight lang="raku" perl6line># 20200721 Raku programming solution
 
my \freqs = < 261.6 293.6 329.6 349.2 392.0 440.0 493.9 523.3 >;
Line 248 ⟶ 397:
 
sub getNote (\freq) {
my $index = +freqs;
for (0..^$index) { $index = $_ and last if freq ≤ freqs[$_] { $index = $_ ; last } }
given $index {
when 0 { "Doh-" }
when +freqs { "doh+" }
default { freqs[$index] - freq ≤ freq - freqs[$index-1]
?? notes[$index] ~ "-" !! notes[$index-1] ~ "+" }
}
Line 263 ⟶ 412:
# https://stackoverflow.com/a/49081648/3386748
 
my $sampleRate = [+] Blob.new(@$file[24..27]).pairs.map: {$_.value*256**$_.key}read-uint32(0,LittleEndian);
# self-ref: [+] @$file[24..27].pairs.map: {$_.value*256**$_.key};
say "Sample Rate : ", $sampleRate;
 
my $dataLength = [+] Blob.new(@$file[40..43]).pairs.map: {$_.value*256**$_.key}read-uint32(0,LittleEndian);
# self-ref: [+] @$file[40..43].pairs.map: {$_.value*256**$_.key};
my $duration = $dataLength / $sampleRate;
say "Duration : ", $duration;
 
my Num ( $sum , $sampleRateF ) = ( 0e0 0, $sampleRate.Num ) ;
my $nbytes = 20;
 
Line 277 ⟶ 428:
for @$file[44..*].rotor($sampleRate) -> $data {
for (1..$nbytes) -> $k {
my Num $bf = @$data[$k].Num / 32e032;
my Num $freqsum += $bf.asin *× $sampleRateF / ( 2e02 *× π *× $k.Num );
$sum += $freq;
}
}
 
my Num $cav = $sum / ( $duration.Num * $nbytes.Num );
say "Computed average frequency = ",{$cav.fmt("'%.1f"'),"} Hz (",{getNote($cav),"})";
 
my $aav = ([+] freqs) / freqs;
$sum = 0e0;
say "Actual average frequency = {$aav.fmt('%.1f')} Hz ({getNote($aav)})";</syntaxhighlight>
$sum += freqs[$_] for 0..^+freqs;
my Num $aav = $sum / +freqs.Num;
say "Actual average frequency = ",$aav.fmt("%.1f")," Hz (",getNote($aav),")"</lang>
{{out}}
<pre>go run Musical_scale.go
Line 300 ⟶ 448:
Computed average frequency = 387.1 Hz (Soh-)
Actual average frequency = 385.4 Hz (Soh-)
</pre>
 
=={{header|V (Vlang)}}==
{{trans|go}}
As an example, we analyze the .wav file (notes.wav) created by the [[https://rosettacode.org/wiki/Musical_scale#Vlang Musical Scale]] task.
<syntaxhighlight lang="v (vlang)">import os
import math
import encoding.binary
 
const (
freqs = [261.6, 293.6, 329.6, 349.2, 392.0, 440.0, 493.9, 523.3]
notes = ["Doh", "Ray", "Mee", "Fah", "Soh", "Lah", "Tee", "doh"]
)
fn get_note(freq f64) string {
mut index := freqs.len
for i in 0..freqs.len {
if freq <= freqs[i] {
index = i
break
}
}
match index {
0 {
return "Doh-"
}
freqs.len {
return "doh+"
}
else {
if freqs[index]-freq <= freq-freqs[index-1] {
return '${notes[index]}-'
}
return '${notes[index-1]}+'
}
}
}
fn main() {
mut file := os.open("notes.wav")?
defer {
file.close()
}
mut hdr := []byte{len: 44}
file.read(mut &hdr)?
 
// check header parameters
sample_rate := int(binary.little_endian_u32(hdr[24..28]))
println("Sample Rate : $sample_rate")
data_length := int(binary.little_endian_u32(hdr[40..]))
duration := data_length / sample_rate
println("Duration : $duration")
mut sum := 0.0
sample_rate_f := f64(sample_rate)
mut data := []byte{len: sample_rate}
nbytes := 20
println("Bytes examined : $nbytes per sample")
for _ in 0..duration {
file.read(mut &data)?
for i := 1; i <= nbytes; i++ {
bf := f64(data[i]) / 32
freq := math.asin(bf) * sample_rate_f / (f64(i) * math.pi * 2)
sum += freq
}
}
cav := sum / (f64(duration) * f64(nbytes))
println("\nComputed average frequency = ${cav:.1} Hz (${get_note(cav)})")
sum = 0.0
for i in 0..freqs.len {
sum += freqs[i]
}
aav := sum / f64(freqs.len)
println("Actual average frequency = ${aav:.1} Hz (${get_note(aav)})")
}</syntaxhighlight>
 
{{out}}
<pre>
Sample Rate : 44100
Duration : 8
Bytes examined : 20 per sample
 
Computed average frequency = 387.1 Hz (Soh-)
Actual average frequency = 385.4 Hz (Soh-)</pre>
 
=={{header|Wren}}==
{{trans|Go}}
{{libheader|Wren-crypto}}
{{libheader|Wren-fmt}}
{{libheader|Wren-math}}
{{libheader|Wren-seq}}
We analyze the .wav file (musical_scale.wav) created by the [[Musical scale]] task.
<syntaxhighlight lang="wren">import "io" for File
import "./crypto" for Bytes
import "./fmt" for Fmt
import "./math" for Nums
import "./seq" for Lst
 
var freqs = [261.6, 293.6, 329.6, 349.2, 392.0, 440.0, 493.9, 523.3]
var notes = ["Doh", "Ray", "Mee", "Fah", "Soh", "Lah", "Tee", "doh"]
 
var getNote = Fn.new { |freq|
var n = freqs.count
var index = n
for (i in 0...n) {
if (freq <= freqs[i]) {
index = i
break
}
}
if (index == 0) {
return "Doh-"
} else if (index == n) {
return "doh+"
} else {
if (freqs[index] - freq <= freq - freqs[index-1]) {
return notes[index] + "-"
}
return notes[index-1] + "+"
}
}
 
var bytes = File.read("musical_scale.wav").bytes.toList
var hdr = bytes[0..43]
 
// check header parameters
var sampleRate = Bytes.toIntLE(hdr[24..27])
System.print("Sample Rate : %(sampleRate)")
var dataLength = Bytes.toIntLE(hdr[40..-1])
var duration = dataLength / sampleRate
System.print("Duration : %(duration)")
 
var sum = 0
var nbytes = 20
System.print("Bytes examined : %(nbytes) per sample")
for (data in Lst.chunks(bytes[44..-1], sampleRate)) {
for (i in 1..nbytes) {
var bf = data[i] / 32
var freq = bf.asin * sampleRate / (i * Num.pi * 2)
sum = sum + freq
}
}
var cav = sum / (duration * nbytes)
Fmt.print("\nComputed average frequency = $.1f Hz ($s)", cav, getNote.call(cav))
var aav = Nums.mean(freqs)
Fmt.print("Actual average frequency = $.1f Hz ($s)", aav, getNote.call(aav))</syntaxhighlight>
 
{{out}}
<pre>
Sample Rate : 44100
Duration : 8
Bytes examined : 20 per sample
 
Computed average frequency = 387.1 Hz (Soh-)
Actual average frequency = 385.4 Hz (Soh-)
</pre>
 
9,476

edits