home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / MM1 / SOUNDUTILS / mm1_tracker.lzh / TRACKER4.6 / Amiga / audio.c < prev    next >
Text File  |  1994-11-24  |  8KB  |  374 lines

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