www.sas.com > SAS UK > In the Know Homepage Search | Contact Us     
SAS UK Newsletter Banner SAS - The power to know(tm)  

Name that Tune using the SAS CALL SOUND Routine!

Here's some example code that illustrates how the datastep and the call sound routine can be used to generate a song!

 
/*Define Length of 4/4 Note*/
%let BaseLength=2000;

data Noten;
  Length Note $5. Mode $1. Type $4.;
  retain BaseLength &BaseLength
         Staccato_Lag 0.2;
  BaseFreq=440;
  label Note='Note'
        Type='Type of Note, e.g. 1/4'
        Mode='Mode (Staccato/Legato)'
        Staccato_Lag='Short break before note to 
                      perform staccato'
        BaseFreq='Frequency of base-note A'
        Length='Length of Note'
        BaseLength='Length of Time ';
  /*Define Array containing Scale*/
  array Scale(0:11) $3 _temporary_
    ('A' 'AIS' 'H' 'C' 'CIS' 'D' 'DIS' 'E' 'F'
     'FIS' 'G' 'GIS');
  /*Get file defined in macro-var file*/
  input Note Type Mode;
  /*Get the length of a Note in ms from input
    Character Column 'Type' in format x/y*/
  if index(Type,'/') then
     length=Baselength*
            input(scan(Type,1,'/'),8.)/input(scan(Type,2,'/'),8.);
  else length=Baselength*input(scan(Type,1,'/'),8.);
  Note=upcase(Note);
  select(Note);
     when('DES') Note='CIS';
     when('ES')  Note='DIS';
     when('GES') Note='FIS';
     when('AS')  Note='GIS';
     when('B')   Note='AIS';
     otherwise;
 end;
  /*If Note contains a plus or minus sign the tone should be x octave
  higher or lower according to the integer x following
  the sign. This is performed by multiplying the 
  base Frequency BaseFreq by 2**(sign*x)  */
  AnyPlusOrMinus=indexc(Note,'-','+');
  if AnyPlusOrMinus then do;
    higherOrlower=input(substr(Note,AnyPlusOrMinus+1),1.);
    if substr(Note,AnyPlusOrMinus,1)='-' then
       higherOrLower=-1*higherOrLower;
    BaseFreq=BaseFreq*(2**(higherOrLower));
    Note=scan(Note,1,'+-');
  end;
  /*If PAUSE then perform break of length LENGTH*/
  if Note='PAUSE' then do;
     /*Delay for Length*/
     start=time();
     end=start+Length/1000;
     do while(time() < end);
     end;
     drop start end; 
 end;
 /*Now create the Frequeny (if not PAUSE)
 and sound. Frequency increases by factor
 2**(1/12) for each halftone*/
 else do i=0 to 11;
    if Note= Scale[i] then do;
         Frequency=BaseFreq*(2**(i/12));
         if mode='S' then do;
            /*if Staccato then Delay for Staccato_lag
            before creating sound*/
            start=time();
            end=start+(Length*Staccato_Lag/1000);
            do while(time() < end);
            end;
            drop start end; 
            /*Correct Length by Staccato_lag*/
            Length=Length-Length*Staccato_lag; 
         end;
         call sound(frequency,Length);
         /*Finish do-loop*/
         i=12;
    end;
  end;
cards;
h     1/16   L   
a     1/16   L 
gis-1 1/16   L
a     1/16   L
c     1/8    L 
PAUSE 1/8    L
d     1/16   L 
c     1/16   L
h     1/16   L 
c     1/16   L 
e     1/8    L
PAUSE 1/8    L
f     1/16   L 
e     1/16   L 
dis   1/16   L
e     1/16   L
h+1   1/16   L
a+1   1/16   L
gis   1/16   L
a+1   1/16   L
h+1   1/16   L
a+1   1/16   L
gis   1/16   L
a+1   1/16   L
c+1   1/4    L
a+1   1/8    S
c+1   1/8    S
g     1/24   L
a+1   1/24   L
h+1   1/24   L
a+1   1/8    S
g     1/8    S
a+1   1/8    S
g     1/24   L
a+1   1/24   L
h+1   1/24   L
a+1   1/8    S
g     1/8    S
a+1   1/8    S
h+1   1/8    S
a+1   1/8    S
g     1/8    S
fis   1/8    S
e     1/8    S  
PAUSE 1/8    L 
h     1/16   L  
a     1/16   L 
gis-1 1/16   L
a     1/16   L
c     1/8    L 
PAUSE 1/8    L
d     1/16   L 
c     1/16   L
h     1/16   L 
c     1/16   L 
e     1/8    L
PAUSE 1/8    L
f     1/16   L 
e     1/16   L 
dis   1/16   L
e     1/16   L
h+1   1/16   L
a+1   1/16   L
gis   1/16   L
a+1   1/16   L
h+1   1/16   L 
a+1   1/16   L
gis   1/16   L
a+1   1/16   L
c+1   1/4    L  
a+1   1/8   S
h+1   1/8   S
C+1   1/8   S
h+1   1/8   S
a+1   1/8   S
gis   1/8   S
a+1   1/8   S
e     1/8   S
f     1/8   S
d     1/8   S
c     1/4   L
c     1/16  L
h     1/16  L
a     1/16  L
h     1/16  L
a     1/8   S   
PAUSE 1/8   L 
;
run;