#!/usr/bin/perl -w -I/usr/lib/lcaspeex use soundcard; use funkylevels; ### VALUES TO PLAY WITH ##################################################### $SOUND_DEVICE = "/dev/dsp"; # select recording format params: (see linux/soundcard.h) $ENCODING = AFMT_S16_LE; # (16-bit signed, little endian) # $ENCODING = AFMT_U8; # (8-bit unsigned universal standard) $STEREO = 0; # 0=mono, 1=stereo $RATE = 16000; # choices for speex: 8000, 16000, 32000 ############################################################################# $BYTE_RATE = 0; # to be set. $retry_count = 0; use Fcntl; use IO::Handle; STDERR->autoflush(1); sub cpack { my $location = shift; my $new = pack "L", $$location; $$location = $new; } sub cunpack { my $location = shift; my $new = unpack "L", $$location; $$location = $new; } sub opendsp { my ($encoding, $stereo, $rate) = @_; sysopen(DSP, $SOUND_DEVICE, O_RDONLY) || die "Couldn't open sound device $SOUND_DEVICE"; cpack \$encoding; cpack \$stereo; cpack \$rate; defined(ioctl(DSP, SNDCTL_DSP_SETFMT, $encoding)) || die "Couldn't set dsp format"; defined(ioctl(DSP, SNDCTL_DSP_STEREO, $stereo)) || die "Couldn't set dsp channels"; defined(ioctl(DSP, SNDCTL_DSP_SPEED, $rate)) || die "Couldn't set dsp rate"; cunpack \$encoding; cunpack \$stereo; cunpack \$rate; $BYTE_RATE = $RATE * ($STEREO+1) * $ENCODING/8; # dangerous hack (* $ENC/8) printf STDERR "Recording in %s at %d Hz with %s encoding (%d B/s)\n", ($STEREO==0)?"mono":"stereo", $RATE, ($ENCODING==AFMT_S16_LE)?"16-bit signed": ($ENCODING==AFMT_U8)?"8-bit unsigned":"unknown", $BYTE_RATE; 1; } sub closedsp { close DSP; } ############################################################################# use Time::Local; opendsp($ENCODING, $STEREO, $RATE); $outpipe = "|sox "; $outpipe .= "-r $RATE "; $outpipe .= "-s -w " if $ENCODING == AFMT_S16_LE; $outpipe .= "-u -b " if $ENCODING == AFMT_U8; $outpipe .= "-c ".($STEREO+1)." "; $outpipe .= "-t raw - "; $outpipe .= "-t wav sample.wav"; open WAVE, $outpipe || die "Couldn't open sox pipe"; for ($i = 0; $i < 10*25; $i++) { $count = sysread(DSP, $buffer, $BYTE_RATE/25); # read 1 second if (defined $count) { #print STDERR "#"; print WAVE $buffer || die "Couldn't write to file"; funkylevels::addlevel $buffer; funkylevels::drawlevel; } else { # dont die "Error occured reading from dsp"; # just reopen the device and cross your fingers. close DSP; ($retry_count == 99) && die "Too many errors reading dsp"; print STDERR "Error reading from dsp. Retry #$count.\n"; opendsp($ENCODING, $STEREO, $RATE); $retry_count++; next; } } closedsp;