gus_sample.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. * Routines for Gravis UltraSound soundcards - Sample support
  3. * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
  4. *
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. *
  20. */
  21. #include <sound/driver.h>
  22. #include <linux/time.h>
  23. #include <sound/core.h>
  24. #include <sound/gus.h>
  25. /*
  26. *
  27. */
  28. static void select_instrument(snd_gus_card_t * gus, snd_gus_voice_t * v)
  29. {
  30. snd_seq_kinstr_t *instr;
  31. #if 0
  32. printk("select instrument: cluster = %li, std = 0x%x, bank = %i, prg = %i\n",
  33. v->instr.cluster,
  34. v->instr.std,
  35. v->instr.bank,
  36. v->instr.prg);
  37. #endif
  38. instr = snd_seq_instr_find(gus->gf1.ilist, &v->instr, 0, 1);
  39. if (instr != NULL) {
  40. if (instr->ops) {
  41. if (!strcmp(instr->ops->instr_type, SNDRV_SEQ_INSTR_ID_SIMPLE))
  42. snd_gf1_simple_init(v);
  43. }
  44. snd_seq_instr_free_use(gus->gf1.ilist, instr);
  45. }
  46. }
  47. /*
  48. *
  49. */
  50. static void event_sample(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
  51. {
  52. if (v->sample_ops && v->sample_ops->sample_stop)
  53. v->sample_ops->sample_stop(p->gus, v, SAMPLE_STOP_IMMEDIATELY);
  54. v->instr.std = ev->data.sample.param.sample.std;
  55. if (v->instr.std & 0xff000000) { /* private instrument */
  56. v->instr.std &= 0x00ffffff;
  57. v->instr.std |= (unsigned int)ev->source.client << 24;
  58. }
  59. v->instr.bank = ev->data.sample.param.sample.bank;
  60. v->instr.prg = ev->data.sample.param.sample.prg;
  61. select_instrument(p->gus, v);
  62. }
  63. static void event_cluster(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
  64. {
  65. if (v->sample_ops && v->sample_ops->sample_stop)
  66. v->sample_ops->sample_stop(p->gus, v, SAMPLE_STOP_IMMEDIATELY);
  67. v->instr.cluster = ev->data.sample.param.cluster.cluster;
  68. select_instrument(p->gus, v);
  69. }
  70. static void event_start(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
  71. {
  72. if (v->sample_ops && v->sample_ops->sample_start)
  73. v->sample_ops->sample_start(p->gus, v, ev->data.sample.param.position);
  74. }
  75. static void event_stop(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
  76. {
  77. if (v->sample_ops && v->sample_ops->sample_stop)
  78. v->sample_ops->sample_stop(p->gus, v, ev->data.sample.param.stop_mode);
  79. }
  80. static void event_freq(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
  81. {
  82. if (v->sample_ops && v->sample_ops->sample_freq)
  83. v->sample_ops->sample_freq(p->gus, v, ev->data.sample.param.frequency);
  84. }
  85. static void event_volume(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
  86. {
  87. if (v->sample_ops && v->sample_ops->sample_volume)
  88. v->sample_ops->sample_volume(p->gus, v, &ev->data.sample.param.volume);
  89. }
  90. static void event_loop(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
  91. {
  92. if (v->sample_ops && v->sample_ops->sample_loop)
  93. v->sample_ops->sample_loop(p->gus, v, &ev->data.sample.param.loop);
  94. }
  95. static void event_position(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
  96. {
  97. if (v->sample_ops && v->sample_ops->sample_pos)
  98. v->sample_ops->sample_pos(p->gus, v, ev->data.sample.param.position);
  99. }
  100. static void event_private1(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
  101. {
  102. if (v->sample_ops && v->sample_ops->sample_private1)
  103. v->sample_ops->sample_private1(p->gus, v, (unsigned char *)&ev->data.sample.param.raw8);
  104. }
  105. typedef void (gus_sample_event_handler_t)(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v);
  106. static gus_sample_event_handler_t *gus_sample_event_handlers[9] = {
  107. event_sample,
  108. event_cluster,
  109. event_start,
  110. event_stop,
  111. event_freq,
  112. event_volume,
  113. event_loop,
  114. event_position,
  115. event_private1
  116. };
  117. void snd_gus_sample_event(snd_seq_event_t *ev, snd_gus_port_t *p)
  118. {
  119. int idx, voice;
  120. snd_gus_card_t *gus = p->gus;
  121. snd_gus_voice_t *v;
  122. unsigned long flags;
  123. idx = ev->type - SNDRV_SEQ_EVENT_SAMPLE;
  124. if (idx < 0 || idx > 8)
  125. return;
  126. for (voice = 0; voice < 32; voice++) {
  127. v = &gus->gf1.voices[voice];
  128. if (v->use && v->client == ev->source.client &&
  129. v->port == ev->source.port &&
  130. v->index == ev->data.sample.channel) {
  131. spin_lock_irqsave(&gus->event_lock, flags);
  132. gus_sample_event_handlers[idx](ev, p, v);
  133. spin_unlock_irqrestore(&gus->event_lock, flags);
  134. return;
  135. }
  136. }
  137. }