Skip to content

Instantly share code, notes, and snippets.

@peyo22
Forked from windytan/whistle-encode.pl
Created November 18, 2015 13:12
Show Gist options
  • Select an option

  • Save peyo22/3e44ec95d4ecc2f2da9f to your computer and use it in GitHub Desktop.

Select an option

Save peyo22/3e44ec95d4ecc2f2da9f to your computer and use it in GitHub Desktop.

Revisions

  1. @windytan windytan revised this gist Oct 10, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions whistle-encode.pl
    Original file line number Diff line number Diff line change
    @@ -12,8 +12,8 @@
    my $risetime = 0.09; # rise/fall slide duration
    my $riseband = 0.7 * $fc; # bandwidth thereof
    my $padding = 0.5; # silence before and after, sec
    my $f_am = 20; # AM noise frequency
    my $depth_am = 0.18; # AM noise modulation index
    my $f_am = 20; # AM distortion frequency
    my $depth_am = 0.18; # AM distortion modulation index
    my $signal_gain = dB(0); # overall signal gain
    my $noise_gain = dB(12); # overall noise gain post-bandpass
    my $noise_shift = 1.0; # noise shift from harmonic (1 = none)
  2. @windytan windytan revised this gist Oct 10, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion whistle-encode.pl
    Original file line number Diff line number Diff line change
    @@ -97,6 +97,6 @@
    close $stream;

    sub dB { 10 ** ($_[0] / 20); }
    sub pcmWord { pack "s", round($_[0] * 0x7FFF); }
    sub pcmWord { pack "s", round($_[0] * (2**16) / 2); }
    sub phaseInc { 2 * 3.14159 * $_[0] / $fs; }
    sub round { $_[0] >= 0 ? int($_[0] + .5) : int($_[0] - .5); }
  3. @windytan windytan revised this gist Oct 10, 2015. 1 changed file with 7 additions and 4 deletions.
    11 changes: 7 additions & 4 deletions whistle-encode.pl
    Original file line number Diff line number Diff line change
    @@ -35,6 +35,8 @@

    open my $stream, '|-', 'sox -t .s16 -c 1 -r ' . $fs . ' - ' . $outfile
    or die $!;

    binmode($stream) or die $!;

    print $stream pcmWord(0) x ($padding * $fs);

    @@ -45,14 +47,14 @@
    $f = $fc - $riseband + ($t/$risetime * $riseband);
    $vol = $t/$risetime;
    $harmonics[0] = ($t < $risetime * .66 ? 0 :
    ($t-$risetime * .66) / ($risetime * .66));
    ($t-$risetime * .66) / ($risetime * .33));

    } elsif ($t > $risetime + $dur) {
    # release
    $f = $fc - ($t-$dur-$risetime) / $risetime * $riseband;
    $vol = dB(0) - ($t-$dur-$risetime) / $risetime;
    $harmonics[0] = ($t-$dur-$risetime > $risetime * .33 ? 0 :
    dB(0) - (($t-$dur-$risetime) * .33) / ($risetime * .33));
    dB(0) - ($t-$dur-$risetime) / ($risetime * .33));

    } else {

    @@ -95,5 +97,6 @@
    close $stream;

    sub dB { 10 ** ($_[0] / 20); }
    sub pcmWord { pack "s", $_[0] * 0x7FFF; }
    sub phaseInc { 2 * 3.14159 * $_[0] / $fs; }
    sub pcmWord { pack "s", round($_[0] * 0x7FFF); }
    sub phaseInc { 2 * 3.14159 * $_[0] / $fs; }
    sub round { $_[0] >= 0 ? int($_[0] + .5) : int($_[0] - .5); }
  4. @windytan windytan revised this gist Oct 10, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions whistle-encode.pl
    Original file line number Diff line number Diff line change
    @@ -18,7 +18,7 @@
    my $noise_gain = dB(12); # overall noise gain post-bandpass
    my $noise_shift = 1.0; # noise shift from harmonic (1 = none)
    my $lp_alfa_fm = 0.004; # signal pre-fm lopass bandwidth
    my $lp_alfa_noise = 0.009; # noise bandpass bandwidth
    my $bp_alfa_noise = 0.009; # noise bandpass bandwidth
    my $fshift = 0.077 * $fc; # FSK shift

    # relative harmonic powers
    @@ -72,7 +72,7 @@
    $prev_f = $f_filtered;

    my $noise = rand() - .5;
    my $noise_filtered = $lp_alfa_noise * $noise + (1 - $lp_alfa_noise) *
    my $noise_filtered = $bp_alfa_noise * $noise + (1 - $bp_alfa_noise) *
    $prev_noise;
    $prev_noise = $noise_filtered;

  5. @windytan windytan revised this gist Oct 10, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions whistle-encode.pl
    Original file line number Diff line number Diff line change
    @@ -41,14 +41,14 @@
    for (my $t = 0; $t < $risetime * 2 + $dur; $t += 1/$fs) {

    if ($t < $risetime) {

    # attack
    $f = $fc - $riseband + ($t/$risetime * $riseband);
    $vol = $t/$risetime;
    $harmonics[0] = ($t < $risetime * .66 ? 0 :
    ($t-$risetime * .66) / ($risetime * .66));

    } elsif ($t > $risetime + $dur) {

    # release
    $f = $fc - ($t-$dur-$risetime) / $risetime * $riseband;
    $vol = dB(0) - ($t-$dur-$risetime) / $risetime;
    $harmonics[0] = ($t-$dur-$risetime > $risetime * .33 ? 0 :
  6. @windytan windytan revised this gist Oct 10, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions whistle-encode.pl
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,10 @@
    # windytan's pea whistle encoder
    # http://www.windytan.com/2015/10/pea-whistle-steganography.html

    use warnings;
    use strict;

    my $data = $ARGV[0] // "OHAI!";
    my $outfile = "whistle.wav";

    my $fs = 44100; # sample rate
    my $fc = 2600; # whistle pitch
    @@ -33,7 +33,7 @@
    my $f, my $f_filtered, my $vol;
    my $ph_am, my $ph_fm;

    open my $stream, '|-', 'sox -t .s16 -c 1 -r ' . $fs . ' - whistle.wav'
    open my $stream, '|-', 'sox -t .s16 -c 1 -r ' . $fs . ' - ' . $outfile
    or die $!;

    print $stream pcmWord(0) x ($padding * $fs);
  7. @windytan windytan revised this gist Oct 10, 2015. 1 changed file with 34 additions and 32 deletions.
    66 changes: 34 additions & 32 deletions whistle-encode.pl
    Original file line number Diff line number Diff line change
    @@ -1,25 +1,25 @@
    # Oona Räisänen's pea whistle encoder
    # windytan's pea whistle encoder
    # http://www.windytan.com/2015/10/pea-whistle-steganography.html

    use warnings;
    use strict;

    my $data = $ARGV[0] // "OHAI!";

    my $fs = 44100; # sample rate
    my $fc = 2600; # whistle pitch
    my $bps = 100; # data speed
    my $risetime = 0.09; # rise/fall slide duration
    my $riseband = 0.7 * $fc; # bandwidth thereof
    my $padding = 0.5; # silence before and after, sec
    my $f_am = 20; # AM noise frequency
    my $vol_am = 0.18; # AM noise modulation index
    my $sig_vol = dB(0); # overall signal gain
    my $noise_vol = dB(12); # overall noise gain after bandpass
    my $noise_shift = 1.0; # noise shift from harmonic (1 = none)
    my $lp_alfa_fm = 0.004; # pre-fm lopass bandwidth
    my $lp_alfa_noise = 0.009; # noise bandpass bandwidth
    my $fshift = 0.077 * $fc; # FSK shift
    my $data = $ARGV[0] // "OHAI!";

    my $fs = 44100; # sample rate
    my $fc = 2600; # whistle pitch
    my $bps = 100; # data speed
    my $risetime = 0.09; # rise/fall slide duration
    my $riseband = 0.7 * $fc; # bandwidth thereof
    my $padding = 0.5; # silence before and after, sec
    my $f_am = 20; # AM noise frequency
    my $depth_am = 0.18; # AM noise modulation index
    my $signal_gain = dB(0); # overall signal gain
    my $noise_gain = dB(12); # overall noise gain post-bandpass
    my $noise_shift = 1.0; # noise shift from harmonic (1 = none)
    my $lp_alfa_fm = 0.004; # signal pre-fm lopass bandwidth
    my $lp_alfa_noise = 0.009; # noise bandpass bandwidth
    my $fshift = 0.077 * $fc; # FSK shift

    # relative harmonic powers
    my @harmonics = (dB(0), dB(-17), dB(-33), dB(-28), dB(-31), dB(-44));
    @@ -30,15 +30,15 @@

    my $prev_noise = 0;
    my $prev_f = $fc - $riseband;
    my $f, my $f_filt, my $vol;
    my $f, my $f_filtered, my $vol;
    my $ph_am, my $ph_fm;

    open my $stream, '|-', "sox -t .s16 -c 1 -r $fs - whistle.wav"
    open my $stream, '|-', 'sox -t .s16 -c 1 -r ' . $fs . ' - whistle.wav'
    or die $!;

    print $stream pack("s", 0) x ($padding * $fs);
    print $stream pcmWord(0) x ($padding * $fs);

    for (my $t = 0; $t < $risetime*2 + $dur; $t += 1/$fs) {
    for (my $t = 0; $t < $risetime * 2 + $dur; $t += 1/$fs) {

    if ($t < $risetime) {

    @@ -68,30 +68,32 @@
    $vol = dB(0);
    }

    $f_filt = $lp_alfa_fm * $f + (1 - $lp_alfa_fm) * $prev_f;
    $prev_f = $f_filt;
    $f_filtered = $lp_alfa_fm * $f + (1 - $lp_alfa_fm) * $prev_f;
    $prev_f = $f_filtered;

    my $noise = rand() - .5;
    my $noise_filt = $lp_alfa_noise * $noise + (1 - $lp_alfa_noise) *
    my $noise_filtered = $lp_alfa_noise * $noise + (1 - $lp_alfa_noise) *
    $prev_noise;
    $prev_noise = $noise_filt;
    $prev_noise = $noise_filtered;

    $ph_fm += 2 * 3.14159 * $f_filt / $fs;
    $ph_am += 2 * 3.14159 * $f_am / $fs;
    $ph_fm += phaseInc($f_filtered);
    $ph_am += phaseInc($f_am);

    my $mix = 0;
    for my $n (0..$#harmonics) {
    my $sig = $harmonics[$n] * cos(($n + 1) * $ph_fm);
    $mix += $sig_vol * $sig * (1 + $vol_am * cos($ph_am));
    $mix += $noise_vol * $noise_filt * $noise_harmonics[$n] *
    $mix += $signal_gain * $sig * (dB(0) + $depth_am * cos($ph_am));
    $mix += $noise_gain * $noise_filtered * $noise_harmonics[$n] *
    cos(($n + 1) * ($ph_fm * $noise_shift));
    }

    print $stream pack("s", dB(-14) * $vol * $mix * 0x7FFF);
    print $stream pcmWord(dB(-14) * $vol * $mix);
    }

    print $stream pack("s", 0) x ($padding * $fs);
    print $stream pcmWord(0) x ($padding * $fs);

    close $stream;

    sub dB { 10 ** ($_[0] / 20); }
    sub dB { 10 ** ($_[0] / 20); }
    sub pcmWord { pack "s", $_[0] * 0x7FFF; }
    sub phaseInc { 2 * 3.14159 * $_[0] / $fs; }
  8. @windytan windytan revised this gist Oct 10, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions whistle-encode.pl
    Original file line number Diff line number Diff line change
    @@ -13,9 +13,9 @@
    my $riseband = 0.7 * $fc; # bandwidth thereof
    my $padding = 0.5; # silence before and after, sec
    my $f_am = 20; # AM noise frequency
    my $vol_am = 0.18; # AM modulation index
    my $vol_am = 0.18; # AM noise modulation index
    my $sig_vol = dB(0); # overall signal gain
    my $noise_vol = dB(12); # overall noise gain
    my $noise_vol = dB(12); # overall noise gain after bandpass
    my $noise_shift = 1.0; # noise shift from harmonic (1 = none)
    my $lp_alfa_fm = 0.004; # pre-fm lopass bandwidth
    my $lp_alfa_noise = 0.009; # noise bandpass bandwidth
  9. @windytan windytan revised this gist Oct 8, 2015. 1 changed file with 15 additions and 13 deletions.
    28 changes: 15 additions & 13 deletions whistle-encode.pl
    Original file line number Diff line number Diff line change
    @@ -11,19 +11,19 @@
    my $bps = 100; # data speed
    my $risetime = 0.09; # rise/fall slide duration
    my $riseband = 0.7 * $fc; # bandwidth thereof
    my $padding = 0.5; # silence before and after
    my $padding = 0.5; # silence before and after, sec
    my $f_am = 20; # AM noise frequency
    my $vol_am = 0.18; # amplitude thereof
    my $sig_vol = 1; # overall signal gain
    my $noise_vol = 4; # overall noise gain
    my $noise_shift = 1.0; # from harmonic center (1 = none)
    my $vol_am = 0.18; # AM modulation index
    my $sig_vol = dB(0); # overall signal gain
    my $noise_vol = dB(12); # overall noise gain
    my $noise_shift = 1.0; # noise shift from harmonic (1 = none)
    my $lp_alfa_fm = 0.004; # pre-fm lopass bandwidth
    my $lp_alfa_noise = 0.009; # noise bandpass bandwidth
    my $fshift = 0.077 * $fc; # FSK shift

    # relative harmonic powers
    my @harmonics = (1, 0.141, 0.022, 0.0398, 0.0282, 0.0063);
    my @noise_harmonics = (1, 0.9, 0.8, 0.7, 0.6, 0.5);
    my @harmonics = (dB(0), dB(-17), dB(-33), dB(-28), dB(-31), dB(-44));
    my @noise_harmonics = (dB(0), dB(-1), dB(-2), dB(-3), dB(-4), dB(-6));

    $data = "\xAA\xA7" . pack("C", length($data)) . $data;
    my $dur = length($data) * 8 / $bps;
    @@ -50,22 +50,22 @@
    } elsif ($t > $risetime + $dur) {

    $f = $fc - ($t-$dur-$risetime) / $risetime * $riseband;
    $vol = 1 - ($t-$dur-$risetime) / $risetime;
    $vol = dB(0) - ($t-$dur-$risetime) / $risetime;
    $harmonics[0] = ($t-$dur-$risetime > $risetime * .33 ? 0 :
    1 - (($t-$dur-$risetime) * .33) / ($risetime * .33));
    dB(0) - (($t-$dur-$risetime) * .33) / ($risetime * .33));

    } else {

    $f = $fc;
    $harmonics[0] = 1;
    $harmonics[0] = dB(0);

    my $bit_i = int(($t - $risetime) * $bps);
    my $byte = substr($data, int($bit_i / 8), 1);
    my $bit = ((unpack("C", $byte) >> ($bit_i % 8)) & 1);

    $f = ($bit - .5) * $fshift + $fc;

    $vol = 1;
    $vol = dB(0);
    }

    $f_filt = $lp_alfa_fm * $f + (1 - $lp_alfa_fm) * $prev_f;
    @@ -87,9 +87,11 @@
    cos(($n + 1) * ($ph_fm * $noise_shift));
    }

    print $stream pack("s", 0.2 * $vol * $mix * 0x7FFF);
    print $stream pack("s", dB(-14) * $vol * $mix * 0x7FFF);
    }

    print $stream pack("s", 0) x ($padding * $fs);

    close $stream;
    close $stream;

    sub dB { 10 ** ($_[0] / 20); }
  10. @windytan windytan revised this gist Oct 8, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion whistle-encode.pl
    Original file line number Diff line number Diff line change
    @@ -18,7 +18,7 @@
    my $noise_vol = 4; # overall noise gain
    my $noise_shift = 1.0; # from harmonic center (1 = none)
    my $lp_alfa_fm = 0.004; # pre-fm lopass bandwidth
    my $lp_alfa_noise = 0.009; # noise lopass bandwidth
    my $lp_alfa_noise = 0.009; # noise bandpass bandwidth
    my $fshift = 0.077 * $fc; # FSK shift

    # relative harmonic powers
  11. @windytan windytan revised this gist Oct 7, 2015. 1 changed file with 20 additions and 18 deletions.
    38 changes: 20 additions & 18 deletions whistle-encode.pl
    Original file line number Diff line number Diff line change
    @@ -6,26 +6,28 @@

    my $data = $ARGV[0] // "OHAI!";

    my $fs = 44100;
    my $fc = 2600;
    my $bps = 100;
    my $risetime = 0.09;
    my $padding = 0.5;
    my $f_am = 20;
    my $vol_am = 0.18;
    my $sig_vol = 1;
    my $noise_vol = 4;
    my $noise_shift = 1.0;
    my $lp_alfa_fm = 0.004;
    my $lp_alfa_noise = 0.009;
    my $fshift = 0.0769 * $fc;
    my $riseband = 0.7 * $fc;
    my $fs = 44100; # sample rate
    my $fc = 2600; # whistle pitch
    my $bps = 100; # data speed
    my $risetime = 0.09; # rise/fall slide duration
    my $riseband = 0.7 * $fc; # bandwidth thereof
    my $padding = 0.5; # silence before and after
    my $f_am = 20; # AM noise frequency
    my $vol_am = 0.18; # amplitude thereof
    my $sig_vol = 1; # overall signal gain
    my $noise_vol = 4; # overall noise gain
    my $noise_shift = 1.0; # from harmonic center (1 = none)
    my $lp_alfa_fm = 0.004; # pre-fm lopass bandwidth
    my $lp_alfa_noise = 0.009; # noise lopass bandwidth
    my $fshift = 0.077 * $fc; # FSK shift

    # relative harmonic powers
    my @harmonics = (1, 0.141, 0.022, 0.0398, 0.0282, 0.0063);
    my @noise_harmonics = (1, 0.9, 0.8, 0.7, 0.6, 0.5);

    $data = "\xAA\xA7" . pack("C", length($data)) . $data;
    my $dur = length($data) * 8 / $bps;

    my @harmonics = (1, 0.141, 0.022, 0.0398, 0.0282, 0.0063);
    my @harmonics_noise = (1, 0.9, 0.8, 0.7, 0.6, 0.5);

    my $prev_noise = 0;
    my $prev_f = $fc - $riseband;
    my $f, my $f_filt, my $vol;
    @@ -81,7 +83,7 @@
    for my $n (0..$#harmonics) {
    my $sig = $harmonics[$n] * cos(($n + 1) * $ph_fm);
    $mix += $sig_vol * $sig * (1 + $vol_am * cos($ph_am));
    $mix += $noise_vol * $noise_filt * $harmonics_noise[$n] *
    $mix += $noise_vol * $noise_filt * $noise_harmonics[$n] *
    cos(($n + 1) * ($ph_fm * $noise_shift));
    }

  12. @windytan windytan revised this gist Oct 7, 2015. 1 changed file with 8 additions and 9 deletions.
    17 changes: 8 additions & 9 deletions whistle-encode.pl
    Original file line number Diff line number Diff line change
    @@ -26,17 +26,16 @@
    my @harmonics = (1, 0.141, 0.022, 0.0398, 0.0282, 0.0063);
    my @harmonics_noise = (1, 0.9, 0.8, 0.7, 0.6, 0.5);

    open my $stream, '|-', "sox -t .s16 -c 1 -r $fs - whistle.wav"
    or die $!;

    print $stream pack("s", 0) x ($padding * $fs);

    my $t = 0;
    my $prev_noise = 0;
    my $prev_f = $fc - $riseband;
    my $f, my $f_filt, my $vol;
    my $ph_am, my $ph_fm;

    open my $stream, '|-', "sox -t .s16 -c 1 -r $fs - whistle.wav"
    or die $!;

    print $stream pack("s", 0) x ($padding * $fs);

    for (my $t = 0; $t < $risetime*2 + $dur; $t += 1/$fs) {

    if ($t < $risetime) {
    @@ -58,9 +57,9 @@
    $f = $fc;
    $harmonics[0] = 1;

    my $bitind = int(($t - $risetime) * $bps);
    my $byte = substr($data, int($bitind / 8), 1);
    my $bit = ((ord($byte) >> ($bitind % 8)) & 1);
    my $bit_i = int(($t - $risetime) * $bps);
    my $byte = substr($data, int($bit_i / 8), 1);
    my $bit = ((unpack("C", $byte) >> ($bit_i % 8)) & 1);

    $f = ($bit - .5) * $fshift + $fc;

  13. @windytan windytan revised this gist Oct 7, 2015. 1 changed file with 17 additions and 16 deletions.
    33 changes: 17 additions & 16 deletions whistle-encode.pl
    Original file line number Diff line number Diff line change
    @@ -32,12 +32,12 @@
    print $stream pack("s", 0) x ($padding * $fs);

    my $t = 0;
    my $prevy = 0;
    my $prev_noise = 0;
    my $prev_f = $fc - $riseband;
    my $f, my $f_filt, my $vol;
    my $ph_am, my $ph_fm;
    for (0.. ($risetime+$dur+$risetime) * $fs) {
    $t += 1/$fs;

    for (my $t = 0; $t < $risetime*2 + $dur; $t += 1/$fs) {

    if ($t < $risetime) {

    @@ -59,33 +59,34 @@
    $harmonics[0] = 1;

    my $bitind = int(($t - $risetime) * $bps);
    my $byte = substr($data, int($bitind / 8),1);
    my $byte = substr($data, int($bitind / 8), 1);
    my $bit = ((ord($byte) >> ($bitind % 8)) & 1);

    $f = ($bit-.5)*$fshift + $fc;
    $f = ($bit - .5) * $fshift + $fc;

    $vol = 1;
    }

    $f_filt = $lp_alfa_fm * $f + (1-$lp_alfa_fm) * $prev_f;
    $f_filt = $lp_alfa_fm * $f + (1 - $lp_alfa_fm) * $prev_f;
    $prev_f = $f_filt;

    my $noise = (rand()-.5);
    my $noise_filt = $lp_alfa_noise*$noise + (1-$lp_alfa_noise) * $prevy;
    $prevy = $noise_filt;
    my $noise = rand() - .5;
    my $noise_filt = $lp_alfa_noise * $noise + (1 - $lp_alfa_noise) *
    $prev_noise;
    $prev_noise = $noise_filt;

    $ph_fm += 2 * 3.14159 * $f_filt / $fs;
    $ph_am += 2 * 3.14159 * $f_am / $fs;

    my $total = 0;
    for (0..$#harmonics) {
    my $s = $harmonics[$_] * cos(($_+1) * $ph_fm);
    $total += $sig_vol * $s * (1 + $vol_am * cos($ph_am));
    $total += $noise_vol * $noise_filt * $harmonics_noise[$_] *
    cos(($_+1) * ($ph_fm * $noise_shift));
    my $mix = 0;
    for my $n (0..$#harmonics) {
    my $sig = $harmonics[$n] * cos(($n + 1) * $ph_fm);
    $mix += $sig_vol * $sig * (1 + $vol_am * cos($ph_am));
    $mix += $noise_vol * $noise_filt * $harmonics_noise[$n] *
    cos(($n + 1) * ($ph_fm * $noise_shift));
    }

    print $stream pack("s", 0.2 * $vol * $total * 0x7FFF);
    print $stream pack("s", 0.2 * $vol * $mix * 0x7FFF);
    }

    print $stream pack("s", 0) x ($padding * $fs);
  14. @windytan windytan revised this gist Oct 7, 2015. 1 changed file with 7 additions and 4 deletions.
    11 changes: 7 additions & 4 deletions whistle-encode.pl
    Original file line number Diff line number Diff line change
    @@ -1,9 +1,12 @@
    # Oona Räisänen's pea whistle encoder
    # http://www.windytan.com/2015/10/pea-whistle-steganography.html

    use warnings;
    use strict;

    my $data = $ARGV[0] // "OHAI!";

    my $fs = 96000;
    my $fs = 44100;
    my $fc = 2600;
    my $bps = 100;
    my $risetime = 0.09;
    @@ -76,10 +79,10 @@

    my $total = 0;
    for (0..$#harmonics) {
    my $s = $harmonics[$_] * sin(($_+1) * $ph_fm);
    $total += $sig_vol * $s * (1 + $vol_am*sin($ph_am));
    my $s = $harmonics[$_] * cos(($_+1) * $ph_fm);
    $total += $sig_vol * $s * (1 + $vol_am * cos($ph_am));
    $total += $noise_vol * $noise_filt * $harmonics_noise[$_] *
    sin(($_+1) * ($ph_fm * $noise_shift));
    cos(($_+1) * ($ph_fm * $noise_shift));
    }

    print $stream pack("s", 0.2 * $vol * $total * 0x7FFF);
  15. @windytan windytan revised this gist Oct 7, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion whistle-encode.pl
    Original file line number Diff line number Diff line change
    @@ -17,7 +17,7 @@
    my $lp_alfa_noise = 0.009;
    my $fshift = 0.0769 * $fc;
    my $riseband = 0.7 * $fc;
    $data = "\xAA\xA7".chr(length($data)).$data;
    $data = "\xAA\xA7" . pack("C", length($data)) . $data;
    my $dur = length($data) * 8 / $bps;

    my @harmonics = (1, 0.141, 0.022, 0.0398, 0.0282, 0.0063);
  16. @windytan windytan created this gist Oct 6, 2015.
    90 changes: 90 additions & 0 deletions whistle-encode.pl
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,90 @@
    use warnings;
    use strict;

    my $data = $ARGV[0] // "OHAI!";

    my $fs = 96000;
    my $fc = 2600;
    my $bps = 100;
    my $risetime = 0.09;
    my $padding = 0.5;
    my $f_am = 20;
    my $vol_am = 0.18;
    my $sig_vol = 1;
    my $noise_vol = 4;
    my $noise_shift = 1.0;
    my $lp_alfa_fm = 0.004;
    my $lp_alfa_noise = 0.009;
    my $fshift = 0.0769 * $fc;
    my $riseband = 0.7 * $fc;
    $data = "\xAA\xA7".chr(length($data)).$data;
    my $dur = length($data) * 8 / $bps;

    my @harmonics = (1, 0.141, 0.022, 0.0398, 0.0282, 0.0063);
    my @harmonics_noise = (1, 0.9, 0.8, 0.7, 0.6, 0.5);

    open my $stream, '|-', "sox -t .s16 -c 1 -r $fs - whistle.wav"
    or die $!;

    print $stream pack("s", 0) x ($padding * $fs);

    my $t = 0;
    my $prevy = 0;
    my $prev_f = $fc - $riseband;
    my $f, my $f_filt, my $vol;
    my $ph_am, my $ph_fm;
    for (0.. ($risetime+$dur+$risetime) * $fs) {
    $t += 1/$fs;

    if ($t < $risetime) {

    $f = $fc - $riseband + ($t/$risetime * $riseband);
    $vol = $t/$risetime;
    $harmonics[0] = ($t < $risetime * .66 ? 0 :
    ($t-$risetime * .66) / ($risetime * .66));

    } elsif ($t > $risetime + $dur) {

    $f = $fc - ($t-$dur-$risetime) / $risetime * $riseband;
    $vol = 1 - ($t-$dur-$risetime) / $risetime;
    $harmonics[0] = ($t-$dur-$risetime > $risetime * .33 ? 0 :
    1 - (($t-$dur-$risetime) * .33) / ($risetime * .33));

    } else {

    $f = $fc;
    $harmonics[0] = 1;

    my $bitind = int(($t - $risetime) * $bps);
    my $byte = substr($data, int($bitind / 8),1);
    my $bit = ((ord($byte) >> ($bitind % 8)) & 1);

    $f = ($bit-.5)*$fshift + $fc;

    $vol = 1;
    }

    $f_filt = $lp_alfa_fm * $f + (1-$lp_alfa_fm) * $prev_f;
    $prev_f = $f_filt;

    my $noise = (rand()-.5);
    my $noise_filt = $lp_alfa_noise*$noise + (1-$lp_alfa_noise) * $prevy;
    $prevy = $noise_filt;

    $ph_fm += 2 * 3.14159 * $f_filt / $fs;
    $ph_am += 2 * 3.14159 * $f_am / $fs;

    my $total = 0;
    for (0..$#harmonics) {
    my $s = $harmonics[$_] * sin(($_+1) * $ph_fm);
    $total += $sig_vol * $s * (1 + $vol_am*sin($ph_am));
    $total += $noise_vol * $noise_filt * $harmonics_noise[$_] *
    sin(($_+1) * ($ph_fm * $noise_shift));
    }

    print $stream pack("s", 0.2 * $vol * $total * 0x7FFF);
    }

    print $stream pack("s", 0) x ($padding * $fs);

    close $stream;