in reply to Morse code via sound card input
Reading code will be trickier, since you will need to detect silences (as opposed to signal) and time them. Here is a start, which will display a number between 0 and ~65500, depending on what your soundcard is playing. Start it, and play a sound and you should see the numbers and 0 for silence , also see a VU-Meter based on this below: UPDATE: Code in readmore is a noise meter, ineffective for reading tones
#!/usr/bin/perl use Audio::DSP; #alsamixer must be setup right, AC'97 capture adjusts sensitivity, #just turn it up to 100 for this to work as intended ($buf, $chan, $fmt, $rate) = (4096, 1, 16 , 8000); $dsp = new Audio::DSP(buffer => $buf, channels => $chan, format => $fmt, rate => $rate); $dsp->init() || die $dsp->errstr(); my $samples = 11500; my $num_tot = 0; my $div_tot = 0; # Record x samples of sound for (1..$samples) { #read 16 bits of raw data my $data = $dsp->dread(16) || die $dsp->errstr(); my $num = unpack( 'v', $data ); #filter out baseline noise if($num > 65000){next}else{ print "$num\n"; $num_tot += $num; $div_tot += 32768; #gives a good average } } $dsp->close(); print "\n\nAverage ",sprintf('%0.2f',$num_tot/$div_tot),"\n";
And here is the same idea, applied to a meter. You will need to setup some sort of timer, to time the 0 and non-zero segments, account for noise, and get the sender's speed. Then you need to capture the ons and offs, taking into account the sending speed, and check them against a hash of letters. It sure would be alot easier, if you can preset the sender speed. Autodetection of sender speed seems to be the big obstacle to me.
#!/usr/bin/perl use warnings; use strict; use Tk; use Audio::DSP; use constant PI => 3.1415926; #alsamixer must be setup right, AC'97 capture adjusts sensitivity, #just turn it up to 100 for this to work as intended my ($buf, $chan, $fmt, $rate) = (4096, 1, 16 , 8000); my $dsp = new Audio::DSP(buffer => $buf, channels => $chan, format => $fmt, rate => $rate); $dsp->init() || die $dsp->errstr(); my $mw = MainWindow->new; my $x = 300; my $y = 300; $mw->protocol('WM_DELETE_WINDOW' => sub { &clean_exit }); $mw->fontCreate('big', -family=>'arial', -weight=>'bold', -size=> 36 ); my $count_tot = 0; my $count_max = 0; my $c = $mw->Canvas( -width => $x, -height => $y, -bd => 2, -relief => 'sunken', -background => 'black', )->pack(); $c->createLine( $x/2, $y/2, 10 , $y/2 , -tags => ['needle'], -arrow => 'last', -width => 15, -fill => 'hotpink', ); my $gauge = $c->createArc( 10,10, $x-10,$y-10, -start => 0, -style => 'arc', -width => 5, -extent => 180, -outline => 'skyblue', -tags => ['gauge'], ); my $hub = $c->createArc( ($x/2 - 20), ($y/2 - 20) ,( $x/2 + 20) ,( $y/2 + 20), -start => 90, -extent => 359, -fill => 'lightgreen', -tags => ['hub'], ); my $text = $c->createText( $x/2, $y/2 + 150, -text => $count_max, -font => 'big', -fill => 'yellow', -anchor => 's', -tags => ['text'] ); $c->raise('needle','text'); $c->raise('hub','needle'); $mw->bind('<space>',sub{ &toggle_status }); $mw->waitVisibility; my $timer = $mw->repeat(50,sub{ my $value = &update_meter; $value = sprintf('%2.1f',$value); if($value <= 0){$value = 0 } if($value >= 100){$value = 100} my $pos = $value/100; my $x1 = $x/2 - .95*$x/2 * (cos( $pos * PI )); my $y1 = $y/2 - .95*$y/2 * (sin( $pos * PI )); $c->coords('needle', ($x/2), ($y/2), $x1, $y1); if($value > $count_max){ $count_max = $value } if($value == 0){ $count_max = 0 } $c->itemconfigure($text, -text => $value); $mw->update; }); MainLoop; ######################################################### sub update_meter { my $samples = 15; my $num_tot = 0; my $div_tot = 0; my $value =0; # Record x samples of sound for (1..$samples) { #read 16 bits of raw data my $data = $dsp->dread(16); # || die $dsp->errstr(); my $num = unpack( 'v', $data ); #filter out baseline noise if($num > 65000){next}else{ #print "$num "; $num_tot += $num; $div_tot += 32768; #gives a good average } } if( $div_tot != 0 ){ $value = ($num_tot/$div_tot) * 100; } return $value; } ###################################################################### +# sub clean_exit{ $timer->cancel; $dsp->close(); exit; } ################################################################# __END__
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Morse code via sound card input
by ww (Archbishop) on Jul 07, 2007 at 18:03 UTC | |
by GrandFather (Saint) on Jul 07, 2007 at 19:32 UTC | |
by zentara (Cardinal) on Jul 08, 2007 at 14:28 UTC |