home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / tracker-4.13.lha / tracker / Amiga / audio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-14  |  8.9 KB  |  412 lines

  1. /* amiga/audio.c 
  2.     vi:ts=3 sw=3:
  3.  */
  4. /* $Id: audio.c,v 1.11 1995/02/14 16:51:22 espie Exp espie $
  5.  * $Log: audio.c,v $
  6.  * Revision 1.11  1995/02/14  16:51:22  espie
  7.  * *** empty log message ***
  8.  *
  9.  * Revision 1.10  1995/02/13  22:05:42  espie
  10.  * Implemented new allocation policy.
  11.  * Updated calls to refer to new release.
  12.  *
  13.  * Revision 1.9  1995/01/13  13:31:35  espie
  14.  * *** empty log message ***
  15.  *
  16.  *
  17.  * Revision 1.6  1994/01/08  04:00:52  Espie
  18.  * added obtain_sample, renamed release_audio_channel,
  19.  * new_channel_tag_list.
  20.  * Major change: moved timing computations to the audio server.
  21.  * Pause is now feasible !
  22.  * Better automatic time adjustement.
  23.  * Ability to play long samples.
  24.  * Modified task pseudoinit in case
  25.  * we use an external server.
  26.  * Removed some typecasts.
  27.  * Added SYNC_DO hook facility.
  28.  * FLUSH_BUFFER on end_all.
  29.  * Messages now initialized correctly
  30.  * Added external sound server for debug.
  31.  */
  32.  
  33. #include <proto/exec.h>
  34. #include <proto/timer.h>
  35.  
  36. #include <exec/types.h>
  37. #include <exec/memory.h>
  38. #include <exec/ports.h>
  39.  
  40. #include "defs.h"
  41. #include "extern.h"
  42. #include "song.h"
  43. #include "tags.h"
  44. #include "amiga/amiga.h"
  45.  
  46. ID("$Id: audio.c,v 1.11 1995/02/14 16:51:22 espie Exp espie $")
  47.  
  48. #define AMIGA_MAX_SAMPLE_LENGTH  131072
  49. #define AMIGA_MIN_SAMPLE_LENGTH  2
  50.  
  51. LOCAL void init_audio(void);
  52. LOCAL void (*INIT)(void) = init_audio;
  53.  
  54. XT unsigned int inhibit_output;
  55.  
  56. LOCAL struct Library *TimerBase = 0;
  57. LOCAL struct timerequest *tr = 0;
  58.  
  59. /* remember allocated samples for cleaning up in panic case */
  60. LOCAL struct MinList tracked_list;
  61.  
  62.  
  63. LOCAL void free_things()
  64.    {
  65.    struct MinNode *current, *next;
  66.  
  67.    SCANLIST(current, next, &tracked_list, struct MinNode *)
  68.       FreeVec(current);
  69.    if (TimerBase)
  70.       CloseDevice(tr);
  71.    if (tr)
  72.       FreeVec(tr);
  73.    }
  74.       
  75.  
  76. /* kludge alert: we allocate arbitrary channel numbers around here.
  77.  * This is probably temporary, and definitely NOT the way to go !
  78.  */
  79.  
  80. LOCAL struct audio_channel
  81.    {
  82.    int amiga_number;
  83.    struct sample_info *samp;
  84.    int volume;
  85.    int pitch;
  86.    } chan[4];
  87.  
  88. LOCAL int allocated = 0;
  89. LOCAL int left_allocated = 0;
  90. LOCAL int right_allocated = 0;
  91.  
  92. LOCAL int free_channel[2][3] =
  93.    {
  94.       {0,3,-1},
  95.       {1,2,-1}
  96.    };
  97.  
  98. struct audio_channel *new_channel_tag_list(struct tag *prop)
  99.    {
  100.    struct audio_channel *new;
  101.  
  102.    INIT_ONCE;
  103.  
  104.    new = &chan[allocated];
  105.    while (prop = get_tag(prop))
  106.       {
  107.       switch(prop->type)
  108.          {
  109.       case AUDIO_SIDE:
  110.          switch(prop->data.scalar)
  111.             {
  112.          case LEFT_SIDE:
  113.             new->amiga_number = free_channel[LEFT_SIDE][left_allocated];
  114.             if (new->amiga_number != -1)
  115.                left_allocated++;
  116.             else
  117.                return NULL;
  118.             break;
  119.          case RIGHT_SIDE:
  120.             new->amiga_number = free_channel[RIGHT_SIDE][right_allocated];
  121.             if (new->amiga_number != -1)
  122.                right_allocated++;
  123.             else
  124.                return NULL;
  125.             break;
  126.          default:
  127.             return NULL;
  128.             }
  129.          break;
  130.       default:
  131.          }
  132.       prop++;
  133.       }
  134.          
  135.    allocated++;
  136.    new->samp = empty_sample();
  137.    new->volume = 0;
  138.    new->pitch = 0;
  139.    new->samp = 0;
  140.    return new;
  141.    }
  142.  
  143. void release_audio_channels()
  144.    {
  145.    left_allocated = right_allocated = allocated = 0;
  146.    }
  147.  
  148.  
  149. /* Special sample management on the amiga */
  150. void *alloc_sample(int len)
  151.    {
  152.    char *s;
  153.  
  154.    INIT_ONCE
  155.    
  156.    s = AllocVec(len + sizeof(struct MinNode), MEMF_CHIP | MEMF_CLEAR);
  157.    if (!s)
  158.       return 0;
  159.    AddTail(&tracked_list, (struct Node *)s);
  160.    return s + sizeof(struct MinNode);
  161.    }
  162.  
  163.  
  164. /* note we have to synchronize audio output before we free the sample */
  165. #define sync_audio close_audio
  166.  
  167. void free_sample(char *s)
  168.    {
  169.    sync_audio();
  170.    s -= sizeof(struct MinNode);
  171.    Remove((struct Node *)s);
  172.    FreeVec(s);
  173.    }
  174.  
  175. int obtain_sample(char *start, int l, struct exfile *f)
  176.    {
  177.    return read_file(start, 1, l, f);
  178.    }
  179.  
  180.  
  181. LOCAL void init_timer()
  182.    {
  183.    int error;
  184.  
  185.    tr = AllocVec(sizeof(struct timerequest), MEMF_PUBLIC | MEMF_CLEAR);
  186.    if (!tr)
  187.       end_all("No timerequest");
  188.    error = OpenDevice(TIMERNAME, UNIT_MICROHZ, tr, 0);
  189.    if (error)
  190.       end_all("Could not open timer");
  191.    TimerBase = (struct Library *)tr->tr_node.io_Device;
  192.    }
  193.  
  194.  
  195. LOCAL void init_audio()
  196.    {
  197.    NewList(&tracked_list);
  198.    at_end(free_things);
  199.    init_timer();
  200.    }
  201.  
  202. /* indispensible for not losing memory ! */
  203.  
  204. void __regargs __chkabort()
  205.    {
  206.    }
  207.    
  208. /* audio */
  209.  
  210. /* empty operation on the amiga */
  211. void init_tables(oversample, frequency)
  212. int oversample, frequency;
  213.    {
  214.    }
  215.  
  216. void resample(oversample, number)
  217. int oversample;
  218. int number;
  219.    {
  220.    struct ext_message *msg;   
  221.  
  222.    INIT_ONCE;
  223.    msg = obtain_message();
  224.    msg->data.time.low = (unsigned long)number;
  225.    msg->data.time.high = 0;
  226.    send(msg, TYPE_WAIT);
  227.    }
  228.  
  229.  
  230. /* So you can play long samples with short repeat parts */
  231. LOCAL void play_long_sample(struct audio_channel *au, UBYTE *start, int length)
  232.    {
  233.    struct ext_message *msg, *msg2;
  234.    int chunk;
  235.    while (length >= AMIGA_MIN_SAMPLE_LENGTH)
  236.       {
  237.       chunk = MIN(AMIGA_MAX_SAMPLE_LENGTH, length);
  238.       msg = obtain_message();
  239.       msg2 = obtain_message();
  240.       msg->data.sample.start = start;
  241.       msg->data.sample.length = chunk;
  242.       msg2->data.info.channel_mask = 1<<au->amiga_number;
  243.       msg2->data.info.cycle = 1;
  244.       msg2->data.info.pitch = au->pitch;
  245.       msg2->data.info.volume = au->volume;
  246.       Forbid();
  247.       send(msg, TYPE_SETUP);
  248.       send(msg2, TYPE_CHANGE);
  249.       Permit();
  250.       length -= chunk;
  251.       start += chunk;
  252.       }
  253.    }
  254.  
  255. void play_note(au, samp, pitch)
  256. struct audio_channel *au;
  257. struct sample_info *samp;
  258. int pitch;
  259.    {
  260.    struct ext_message *msg, *msg2;
  261.  
  262.    au->pitch = pitch;
  263.    msg = obtain_message();
  264.    msg->data.info.channel_mask = 1<<au->amiga_number;
  265.    send(msg, TYPE_FLUSH_CHANNEL);
  266.    
  267.    if (samp)
  268.       {
  269.       au->samp = samp;
  270.       if (samp->start)
  271.          {
  272.          play_long_sample(au, samp->start, samp->length);
  273.          if (samp->rp_start)
  274.             {
  275.             msg = obtain_message();
  276.             msg2 = obtain_message();
  277.             msg->data.sample.start = samp->rp_start;
  278.             msg->data.sample.length = samp->rp_length;
  279.             msg2->data.info.channel_mask = 1<<au->amiga_number;
  280.             msg2->data.info.cycle = 0;
  281.             msg2->data.info.pitch = 0;
  282.             msg2->data.info.volume = 0;
  283.             Forbid();
  284.             send(msg, TYPE_SETUP);
  285.             send(msg2, TYPE_CHANGE);
  286.             Permit();
  287.             }  
  288.          }
  289.       }
  290.    }
  291.  
  292. void set_play_pitch(au, pitch)
  293. struct audio_channel *au;
  294. int pitch;
  295.    {
  296.    if (pitch != au->pitch)
  297.       {
  298.       struct ext_message *msg;
  299.  
  300.       au->pitch = pitch;
  301.       msg = obtain_message();
  302.       msg->data.info.channel_mask = 1<<au->amiga_number;
  303.       msg->data.info.pitch = au->pitch;
  304.       msg->data.info.volume = au->volume;
  305.       send(msg, TYPE_CHANGE);
  306.       }
  307.    }
  308.  
  309. void set_play_volume(au, volume)
  310. struct audio_channel *au;
  311. int volume;
  312.    {
  313.    if (volume != au->volume)
  314.       {
  315.       struct ext_message *msg;
  316.  
  317.       au->volume = volume;
  318.       if (au->samp != empty_sample())
  319.          {
  320.          msg = obtain_message();
  321.          msg->data.info.channel_mask = 1<<au->amiga_number;
  322.          msg->data.info.pitch = au->pitch;
  323.          msg->data.info.volume = au->volume;
  324.          send(msg, TYPE_CHANGE);
  325.          }
  326.       }
  327.    }
  328.  
  329. void set_play_position(au, pos)
  330. struct audio_channel *au;
  331. int pos;
  332.    {
  333.    struct ext_message *msg, *msg2;
  334.    
  335.    
  336.    msg = obtain_message();
  337.    msg->data.info.channel_mask = 1<<au->amiga_number;
  338.    send(msg, TYPE_FLUSH_CHANNEL);
  339.  
  340.    if (au->samp->start)
  341.       {
  342.       if (pos < au->samp->length)
  343.          {
  344.          play_long_sample(au, au->samp->start + pos, au->samp->length - pos);
  345.          if (au->samp->rp_start)
  346.             {
  347.             msg = obtain_message();
  348.             msg2 = obtain_message();
  349.             msg->data.sample.start = au->samp->rp_start;
  350.             msg->data.sample.length = au->samp->rp_length;
  351.             msg2->data.info.channel_mask = 1<<au->amiga_number;
  352.             msg2->data.info.cycle = 0;
  353.             msg2->data.info.pitch = 0;
  354.             msg2->data.info.volume = 0;
  355.             Forbid();
  356.             send(msg, TYPE_SETUP);
  357.             send(msg2, TYPE_CHANGE);
  358.             Permit();
  359.             }  
  360.          }
  361.       }
  362.    }
  363.  
  364.  
  365.  
  366. void set_mix(percent)
  367. int percent;
  368.    {
  369.    }
  370.  
  371. int open_audio(f, s)
  372. int f, s;
  373.    {
  374.    ULONG freq;
  375.    LOCAL struct EClockVal dummy;
  376.  
  377.    INIT_ONCE;
  378.  
  379.       /* samples/sec used as a timing unit: 1sec =1 000 000 µs */
  380.    freq = ReadEClock(&dummy);
  381.    return (int)freq;
  382.    }
  383.    
  384. void set_synchro(s)
  385. int s;
  386.    {
  387.    }
  388.  
  389. int update_frequency()
  390.    {
  391.    return 0;
  392.    }
  393.  
  394. void flush_buffer(void)
  395.    {
  396.    }
  397.  
  398. void discard_buffer(void)
  399.    {
  400.    struct ext_message *msg;
  401.    
  402.    inhibit_output++;
  403.    msg = obtain_message();
  404.    send(msg, TYPE_FLUSH_BUFFER);
  405.    msg = obtain_message();
  406.    send(msg, TYPE_SYNC);
  407.    while (msg != await_type(TYPE_SYNC))
  408.       ;
  409.    inhibit_output--;
  410.    }
  411.  
  412.