Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

How can I play music like Basic's SOUND or PLAY?

by Anonymous Monk
on Aug 30, 2000 at 12:52 UTC ( #30268=categorized question: print w/replies, xml ) Need Help??
Contributed by Anonymous Monk on Aug 30, 2000 at 12:52 UTC
Q&A  > input and output


How can I (or even anybody else) play music like Basic's

SOUND 440: SOUND 220: SOUND 110:


Answer: How can I play music like Basic's SOUND or PLAY?
contributed by cianoz

I've found "Audio::Play" on CPAN: The readme claims it can play sound via /dev/audio or NAS under unix and even under WIN32 (with code from timidity, the author says)
I know is not exactly what you are looking for, however there is a little application in the distribution that could suggest you a different approach to the problem.

Answer: How can I play music like Basic's SOUND or PLAY?
contributed by igoryonya

Hi, long time ago, I've made a music playing script. It generates sound waves then sends them to a sound card. I did it as an experiment that sound generation could be done in pure perl without external apps. I was determined to write my own pure perl mp3 player and this player was just the beginning of the project, which got stale for the lack of time, but it doesn't mean that I don't still want to eventually complete that. I actually want to try to create a pure perl mp3 decoder which will read in mp3 files, decode them internally without any external codec by just perl itself into waves and send them to the sound card.

In my script, I added a wave visualization, which you can disable by setting 0 on $displayWave variable; from the script and just leave the sound playing section.

You can also save the output wave to a wav file. I have it commented out at the end.

It accepts a file with notes and plays them.

use Win32::Sound; $displayWave = 1; $range = 256/39; $virtlim = 47; $step = 24; $midofc = 20; @extremes = (0,0); %FqC = ('a', [55,110,220,440,880,1760], 'as',[58.270,116.541,233.082,466.164,932.328,1864.655] +, 'b', [61.735,123.471,246.942,493.883,987.767,1975.533] +, 'c', [65.406,130.813,261.626,523.251,1046.502,2093.005 +], 'cs',[69.296,138.591,277.183,554.365,1108.731,2217.461 +], 'd', [73.416,146.832,293.665,587.330,1174.659,2349.318 +], 'ds',[77.782,155.563,311.127,622.254,1244.508,2489.016 +], 'e', [82.407,164.814,329.628,659.255,1318.510,2637.020 +], 'f', [87.307,174.614,349.228,698.456,1396.913,2793.826 +], 'fs',[92.499,184.997,369.994,739.989,1479.978,2959.955 +], 'g', [97.999,195.998,391.995,783.991,1567.982,3135.963 +], 'gs',[103.826,207.652,415.305,830.609,1661.219,3322.43 +8], 'p',[0,0,0,0,0,0] ); %def = ('octav', 3, 'frac', 4, 'paus', 64); print "Welcome to Perl Music Player V1 by Igor A. Rylov\n". "\n\n\n\tPlaying '$ARGV[0]' file.\n"; open(MUS, "$ARGV[0]"); @notes = (); while(<MUS>){ $_ =~ s/[\n\r\f\cM]+$//; $_ =~ tr/#/s/; $_ = lc($_); @notes = (@notes, split(/\s+/, $_)); } close(MUS); # Create the object $WAV = new Win32::Sound::WaveOut(44100, 8, 2); $data = ""; $osc = 0; foreach $note (@notes){ ($note, $frac) = split('/', $note); $note =~ s/(\d)$//; $octav = $1; $octav = $def{'octav'} if($octav eq ''); $frac = $def{'paus'} if($frac eq '' && $note eq 'p'); $frac = $def{'frac'} if($frac eq '' || $frac eq 0); $counter = 0; $increment = $FqC{$note}[$octav]/44100; $label = (uc($note))."($octav) = $FqC{$note}[$octav]; ".(1/$frac) +." Second; Step = $step\n"; # Generate 44100 samples ( = 1 second) $st = time; for $i (1..(44100/$frac)){ # Calculate the pitch # (range 0..255 for 8 bits) $v = ($note eq 'p')?(0):(sin($counter/2*3.14) * 128 + 128); $extremes[0] = $v if($extremes[0] > $v); $extremes[1] = $v if($extremes[1] < $v); if($displayWave){ if(($osc % ($virtlim * $step)) == 0){ system(cls); print $label; } if(($osc % $step) == 0){ print ' ' x (40 - $midofc + ($v/$range)); print "X\n"; } } ++$osc; # "pack" it twice for left and right $data .= pack("cc", $v, $v); $counter += $increment; } $newt = (time - $st); $step = $newt * $frac if($step == 1); } print "\n\nExtremes: $extremes[0] <=> $extremes[1]\n\n"; $WAV->Load($data); # get it $WAV->Write(); # hear it 1 until $WAV->Status(); # wait for completion # $WAV->Save("sinus.wav"); # write to disk $WAV->Unload(); # drop it
This prog accepts a file with notes. File spec is simple. Just type notes in sequence, separated by space. Notes are defined are written in the form:
(Note)(isSharp)(Octave)length in seconds or fractions of seconds, optional. Default = 1 second
Notes are: a b c d e f g

Sharp Notes are: a# c# d# f# g#

An octave is appended to a note to define it:

a2 d#4

In the above example were used a note from the octave 2 and d sharp note from the octave 4

You can specify their lengths in complete or fractional seconds. Fraction is defined by a slash and a seconds value:

a2/2 d#4/.5 b5

In the above example: a note, octave, 2 seconds; d sharp note, 4th octave, half a second; b from the 5th octave, 1 second (the default, because the length was omitted).

There is a p note, which is a pause

An example Music file:

a4 f#4/2 c4 d4 f4/2 b4 p b4 d#4/2 d4 c4 d#4/2 a4 p a4 d4/2 p d4 e4 f4/2 p f4 g4 a5/2 p a5 b5 c5/1 p b5 d5/2 p d5 a5 b5/2
The note frequencies are defined in FqC. They are probably not the frequencies used in real instruments, but I chose them by manually listening and testing sounds. I didn't have a time to look for the info on the real frequencies for each note used. If anybody knows the real frequencies for each note in each octave, they can be changed in that variable.

Please (register and) log in if you wish to add an answer

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others chilling in the Monastery: (3)
    As of 2020-09-19 13:03 GMT
    Find Nodes?
      Voting Booth?
      If at first I donít succeed, I Ö

      Results (114 votes). Check out past polls.