perlphreak has asked for the wisdom of the Perl Monks concerning the following question:

I am attempting to use a couple of Audio::Data and Audio::Play to generate a DTMF tone using the following script:

#!/usr/local/bin/perl -w use Audio::Data; use Audio::Play; my $freq1 = 1209; my $freq2 = 697; my $pause = 0.25; my $au = Audio::Data->new(rate => 8000); $au->tone($freq1,$pause); $au->tone($freq2,$pause); $au->silence($dot); my $svr = Audio::Play->new; $svr->play($au);

It would appear that these modules don't allow two tones to play simultaneously. Any suggestions on overcoming this limitation? -jj

Edit: g0n - code tags added

Replies are listed 'Best First'.
Re: PERL and DTMF
by eweaver (Sexton) on Dec 18, 2005 at 07:19 UTC

    According to the Audio::Data docs, + is overloaded for additive mixing of two Data objects. So just create a second Data object for your second tone, add them, and save it back to the original object. Make sure when you call silence() that you are not overwriting the original data. You may have to use ->append($data_object->silence(...)) instead of calling silence() directly.

    If, instead, you are trying to concatenate sounds (one sound plays after the other... for instance, a monotonic telephone dialing sequence), then you will have to use appends. Regardless, right now you are just overwriting your previous data with the last tone (or possibly the silence()).

    Check the CPAN docs, they are very clear. It seems like you don't quite understand how Audio::Data represents and processes data. It's sample-based, not some group of functional representations (which could, theoretically, happily co-exist... but even so the usage syntax would probably be different than what you have).

    ~e

Re: PERL and DTMF
by zentara (Cardinal) on Dec 18, 2005 at 11:02 UTC
    You can mix sounds using SDL::Mixer, see Tk Game Sound demo where I use Tk as a front end. But if you just want DTMF tones, you can try Audio::Beep. ( scripts must be run as root ), or Audio::Wav
    #!/usr/bin/perl -w #Usage: $0 [DTMF tones] [play] #i.e. dtmf.pl 18005551212 1 use strict; use Audio::Wav; my @tones; my %dtmf = ( '1' => [ 697, 1209 ], '2' => [ 697, 1336 ], '3' => [ 697, 1477 ], 'A' => [ 697, 1633 ], '4' => [ 770, 1209 ], '5' => [ 770, 1336 ], '6' => [ 770, 1477 ], 'B' => [ 770, 1633 ], '7' => [ 852, 1209 ], '8' => [ 852, 1336 ], '9' => [ 852, 1477 ], 'C' => [ 852, 1633 ], '*' => [ 941, 1209 ], '0' => [ 941, 1336 ], '#' => [ 941, 1477 ], 'D' => [ 941, 1633 ], ); if (@ARGV > 0) { @tones = split'',$ARGV[0]; } else { @tones = sort keys %dtmf; } my $play = $ARGV[1] || '5551212'; my $sample_rate = 22050; my $bits_sample = 16; #my sblive needs 16 my $num_channels = 1; my $pi = 4 * atan2 1, 1; my $duration = 0.5 * $sample_rate; my $wav = new Audio::Wav; my $details = { 'bits_sample' => $bits_sample, 'sample_rate' => $sample_rate, 'channels' => $num_channels, }; my $write = $wav -> write( 'dtmf.wav', $details ); for my $tone (@tones) { my @hz = map { $pi * $_ } @{$dtmf{$tone}}; add_tone(@hz); } $write -> finish(); Win32::Sound::Play('dtmf.wav') if $play && $main::can_play; sub add_tone { my (@hz) = @_; for my $pos ( 0 .. $duration ) { my $time = $pos / $sample_rate; my $val = 63 * sin($time * $hz[0]) + 63 * sin($time * $hz[1]); $write -> write( $val ); } } BEGIN { if ($^O =~ /MSWin32/) { require Win32::Sound; our $can_play = 1; } }

    I'm not really a human, but I play one on earth. flash japh
Re: PERL and DTMF
by neosamuri (Friar) on Dec 18, 2005 at 02:54 UTC

    I really don't know how to do it, but when I was looking at the Audio::Data documentation I noticed that it had overloaded the operators, this may be what you need in order to make the DTMF. I was thinking allong the lines of using the + operator to mix the two tones.

A reply falls below the community's threshold of quality. You may see it by logging in.