home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Prog / U-Z / VideoToolBox Folder / VideoToolboxSources / CreateTrialSnds.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-31  |  5.8 KB  |  169 lines  |  [TEXT/KAHL]

  1. /* CreateTrialSnds.c
  2. Create snd resources for 2afc testing: a "beep" for each presentation,
  3. rightSnd, wrongSnd, and abortSnd for feedback, and a "purr" that I use between 
  4. the presentation and response to indicate to the user that the computer 
  5. is waiting for a response. You can play these sounds by using Apple's SndPlay(), 
  6. or my SndPlay1(), which is in the VideoToolbox. Note that these are proper
  7. resources and are interchangeable with other snd resources, which you can
  8. retrieve by calling GetNamedResource('snd ',"\pSimple Beep"), for example.
  9. You could also use the sound recording capabilities of your Mac to record
  10. spoken words like "right" and "wrong", accessible in the same way.
  11.  
  12. Unlike other routines in VideoToolboxSources, you will probably not use this
  13. routine unaltered. Instead you'll probably modify the code to produce
  14. sounds that suit your own purposes.
  15.  
  16. Note that the sound handles are published as globals. I don't like using globals,
  17. because they make information flow impossible to work out, but in this case
  18. all alternatives seem unreasonably cumbersome.
  19.  
  20. In updating my software from the Sound Driver to the Sound Manager I was
  21. disappointed to discover that the squareWaveSynth supplied by the Sound
  22. Manager doesn't sound at all like the square wave synthesizer of the
  23. Sound Driver. It seems to interpolate, resulting in smoother waveforms that
  24. are inaudible at low frequencies, even if you set the timbre parameter to 255.
  25. E.g. my "purr" is a 22 Hz square wave of which one only hears the clicks at
  26. the transitions, and is thus inaudible after smoothing. Fortunately one can 
  27. recreate the old square wave synthesizer by using the sampledSynth with 
  28. no interpolation, playing from a square wave table, which can be included in the
  29. snd resource. 
  30.  
  31. Note that the beep, which uses the squareWaveSynth, continues playing even while 
  32. interrupts are suspended, e.g. by calling SetPriority(7), while the sounds
  33. produced by the sampledSynth pause while interrupts are suspended. This
  34. implies that the sound chip must implement the squareWaveSynth all by itself.
  35. However, the beep never ends as long as the interrupts remain suspended.
  36. The practical consequence of all this is that you can use "beep" to play
  37. sounds simultaneously with stimuli that (for maximum performance) require
  38. suspension of interrupts.
  39. HISTORY:
  40. 4/1/92    dgp extracted it from DoATrial.c
  41. */
  42. #include "VideoToolbox.h"
  43. #include <Sound.h>
  44.  
  45. Handle beep=NULL,rightSnd=NULL,wrongSnd=NULL,abortSnd=NULL,purr=NULL;
  46.  
  47. typedef struct {            // An 'snd ' resource of type 1. See Inside Mac VI:22-19.
  48.     short format;            // must equal 1
  49.     short numberOfSynths;    // 1 in this structure
  50.     short synth;
  51.     long synthInitOption;
  52.     short numberOfCommands;
  53.     SndCommand commands[];
  54. } Snd1Resource;
  55.  
  56. void CreateTrialSnds(void)
  57. {
  58.     Snd1Resource *s;
  59.     OSErr error;
  60.     SoundHeader **squareWaveTable;
  61.     
  62.     if(beep!=NULL)return;
  63.     
  64.     squareWaveTable=(SoundHeader **)NewHandle(sizeof(SoundHeader)+8);
  65.     if(squareWaveTable==NULL)goto error;
  66.     (*squareWaveTable)->samplePtr=NULL;
  67.     (*squareWaveTable)->length=8;
  68.     (*squareWaveTable)->sampleRate=880*0x10000;    // 880 Hz
  69.     (*squareWaveTable)->loopStart=0;
  70.     (*squareWaveTable)->loopEnd=8;
  71.     (*squareWaveTable)->encode=stdSH;
  72.     (*squareWaveTable)->baseFrequency=57;        // 440 Hz
  73.     (*squareWaveTable)->sampleArea[0]=0;
  74.     (*squareWaveTable)->sampleArea[1]=255;
  75.     (*squareWaveTable)->sampleArea[2]=0;
  76.     (*squareWaveTable)->sampleArea[3]=255;
  77.     (*squareWaveTable)->sampleArea[4]=0;
  78.     (*squareWaveTable)->sampleArea[5]=255;
  79.     (*squareWaveTable)->sampleArea[6]=0;
  80.     (*squareWaveTable)->sampleArea[7]=255;
  81.  
  82.     purr=NewHandle(sizeof(Snd1Resource)+4*sizeof(SndCommand));
  83.     if(purr==NULL)goto error;
  84.     s=(Snd1Resource *)*purr;
  85.     s->format=1;
  86.     s->numberOfSynths=1;
  87.     s->synth=sampledSynth;
  88.     s->synthInitOption=initNoInterp;
  89.     s->numberOfCommands=4;
  90.     s->commands[0].cmd=soundCmd+dataOffsetFlag;
  91.     s->commands[0].param1=0;
  92.     s->commands[0].param2=GetHandleSize(purr);
  93.     s->commands[1].cmd=ampCmd;
  94.     s->commands[1].param1=70;
  95.     s->commands[1].param2=0;
  96.     s->commands[2].cmd=freqCmd;
  97.     s->commands[2].param1=0;
  98.     s->commands[2].param2=1;        // 17 Hz
  99.     s->commands[3].cmd=nullCmd;
  100.     s->commands[3].param1=0;
  101.     s->commands[3].param2=0;
  102.     HLock((Handle)squareWaveTable);
  103.     HandAndHand((Handle)squareWaveTable,purr);    // append squareWaveTable
  104.     DisposeHandle((Handle)squareWaveTable);
  105.     
  106.     abortSnd=purr;
  107.     if(HandToHand(&abortSnd))goto error;
  108.     s=(Snd1Resource *)*abortSnd;
  109.     s->commands[1].cmd=ampCmd;
  110.     s->commands[1].param1=80;
  111.     s->commands[1].param2=0;
  112.     s->commands[2].cmd=freqDurationCmd;
  113.     s->commands[2].param1=2400;
  114.     s->commands[2].param2=69-5*12;    // 27.5 Hz
  115.     s->commands[3].cmd=quietCmd;
  116.     s->commands[3].param1=0;
  117.     s->commands[3].param2=0;
  118.  
  119.     wrongSnd=abortSnd;
  120.     if(HandToHand(&wrongSnd))goto error;
  121.     s=(Snd1Resource *)*wrongSnd;
  122.     s->synthInitOption=0;
  123.     s->commands[1].cmd=ampCmd;
  124.     s->commands[1].param1=100;
  125.     s->commands[1].param2=0;
  126.     s->commands[2].cmd=freqDurationCmd;
  127.     s->commands[2].param1=1200;
  128.     s->commands[2].param2=69-12;    // 880/2 Hz
  129.  
  130.     beep=NewHandle(sizeof(Snd1Resource)+4*sizeof(SndCommand));
  131.     if(beep==NULL)goto error;
  132.     s=(Snd1Resource *)*beep;
  133.     s->format=1;
  134.     s->numberOfSynths=1;
  135.     s->synth=squareWaveSynth;
  136.     s->synthInitOption=0;
  137.     s->numberOfCommands=4;
  138.     s->commands[0].cmd=timbreCmd;
  139.     s->commands[0].param1=20;
  140.     s->commands[0].param2=0;
  141.     s->commands[1].cmd=ampCmd;
  142.     s->commands[1].param1=100;
  143.     s->commands[1].param2=0;
  144.     s->commands[2].cmd=freqDurationCmd;
  145.     s->commands[2].param1=4000;
  146.     s->commands[2].param2=69;        // 880 Hz
  147.     s->commands[3].cmd=quietCmd;
  148.     s->commands[3].param1=0;
  149.     s->commands[3].param2=0;
  150.     
  151.     rightSnd=beep;
  152.     if(HandToHand(&rightSnd))goto error;
  153.     s=(Snd1Resource *)*rightSnd;
  154.     s->commands[0].cmd=timbreCmd;
  155.     s->commands[0].param1=0;
  156.     s->commands[0].param2=0;
  157.     s->commands[1].cmd=ampCmd;
  158.     s->commands[1].param1=100;
  159.     s->commands[1].param2=0;
  160.     s->commands[2].cmd=freqDurationCmd;
  161.     s->commands[2].param1=100;
  162.     s->commands[2].param2=69+12;    // 2*880 Hz
  163.  
  164.     return;
  165.     
  166.     error:
  167.     PrintfExit("CreateTrialSnds: not enough memory\n");
  168. }
  169.