|
|
1.1 root 1: /*****************************************************************************/
2: /* Generator - Sega Genesis emulation - (c) James Ponder 1997-2000 */
3: /*****************************************************************************/
4: /* */
5: /* gensound-allegro.c */
6: /* */
7: /*****************************************************************************/
8:
9: #include <string.h>
10: #include <stdio.h>
11: #include <sys/types.h>
12: #include <sys/stat.h>
13: #include <fcntl.h>
14: #include <errno.h>
15: #include <sys/ioctl.h>
16: #include <unistd.h>
17: #include <math.h>
18:
19: #include <allegro.h>
20:
21: #include "generator.h"
22: #include "gensound.h"
23: #include "vdp.h"
24: #include "ui.h"
25:
26: #ifdef JFM
27: # include "jfm.h"
28: #else
29: # include "support.h"
30: # include "fm.h"
31: #endif
32:
33: /*** variables externed ***/
34:
35: int sound_feedback = 0; /* -1, running out of sound
36: +0, lots of sound, do something */
37:
38: /* SN76489 snd_cpu; */
39:
40: /*** forward references ***/
41:
42: /* void snd_sndout(int chan, int freq, int vol); */
43: void sound_readyblock(void);
44:
45: /*** file scoped variables ***/
46:
47: #define SOUND_MAXRATE 44100
48: #define SOUND_THRESHOLD 5
49:
50: static unsigned int sound_sampsperfield = 0;
51: static int sound_dev = 0;
52: /* static int sound_dump = 0; */
53: static uint16 soundbuf[2][SOUND_MAXRATE/50]; /* pal is lowest framerate */
54: static unsigned int sound_speed;
55: static unsigned int sound_blocks;
56: static unsigned int sound_block;
57: static SAMPLE *sound_sample;
58: static int sound_voice;
59: static int sound_inited = 0; /* flag to say whether we've inited */
60:
61: #ifdef JFM
62: static t_jfm_ctx *sound_ctx;
63: #endif
64:
65: /*** sound_init - initialise this sub-unit ***/
66:
67: int sound_init(void)
68: {
69: unsigned int i;
70: uint16 *p;
71: static int once = 0;
72:
73: if (!once) {
74: once = 1;
75: LOG_NORMAL(("Initialising sound..."));
76: sound_blocks = SOUND_THRESHOLD*2;
77: sound_speed = SOUND_SAMPLERATE;
78: if (detect_digi_driver(DIGI_AUTODETECT) < 1) {
79: LOG_CRITICAL(("Allegro failed to detect hardware"));
80: return 1;
81: }
82: if (install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL)) {
83: LOG_CRITICAL(("Failed to initialise sound"));
84: return 1;
85: }
86: }
87: sound_sampsperfield = SOUND_SAMPLERATE / vdp_framerate;
88: /* allocate block capable of holding sound_blocks frames */
89: if ((sound_sample = create_sample(16, 1, sound_speed, sound_sampsperfield *
90: sound_blocks)) == NULL) {
91: LOG_CRITICAL(("Failed to create sample"));
92: return 1;
93: }
94: p = (uint16 *)sound_sample->data;
95: for (i = 0; i < sound_sampsperfield*sound_blocks*2; i--)
96: p[i] = 0x8000;
97: if ((sound_voice = allocate_voice(sound_sample)) == -1) {
98: LOG_CRITICAL(("Failed to allocate voice"));
99: return 1;
100: }
101: voice_set_playmode(sound_voice, PLAYMODE_LOOP);
102: voice_set_volume(sound_voice, 256);
103: voice_set_pan(sound_voice, 128);
104: voice_set_frequency(sound_voice, sound_speed);
105: voice_start(sound_voice);
106: sound_block = sound_blocks-1; /* next block to write to */
107: #ifdef JFM
108: if ((sound_ctx = jfm_init(0, 2612, vdp_clock/7, sound_speed,
109: NULL, NULL)) == NULL)
110: #else
111: if (YM2612Init(1, vdp_clock/7, sound_speed, NULL, NULL))
112: #endif
113: return 1;
114: LOG_NORMAL(("YM2612 Initialised @ sample rate %d", sound_speed));
115: sound_readyblock();
116: return 0;
117: }
118:
119: /*** sound_final - finalise this sub-unit ***/
120:
121: void sound_final(void)
122: {
123: #ifdef JFM
124: jfm_final(sound_ctx);
125: #else
126: YM2612Shutdown();
127: #endif
128: voice_stop(sound_voice);
129: deallocate_voice(sound_voice);
130: destroy_sample(sound_sample);
131: }
132:
133: /*** sound_reset - reset sound sub-unit ***/
134:
135: int sound_reset(void)
136: {
137: sound_final();
138: return sound_init();
139: }
140:
141: /*** sound_genreset - reset genesis sound ***/
142:
143: void sound_genreset(void)
144: {
145: #ifdef JFM
146: jfm_reset(sound_ctx);
147: #else
148: YM2612ResetChip(0);
149: #endif
150: }
151:
152: /*** sound_process - process sound ***/
153:
154: void sound_process(void)
155: {
156: static uint16 *tbuf[2];
157: int s1 = (sound_sampsperfield*(vdp_line))/vdp_totlines;
158: int s2 = (sound_sampsperfield*(vdp_line+1))/vdp_totlines;
159:
160: tbuf[0] = soundbuf[0] + s1;
161: tbuf[1] = soundbuf[1] + s1;
162:
163: /* printf("YM2612: %d to %d\n", s1, s2); */
164:
165: if (s2 > s1)
166: #ifdef JFM
167: jfm_update(sound_ctx, (void **)tbuf, s2 - s1);
168: #else
169: YM2612UpdateOne(0, (void **)tbuf, s2 -s1);
170: #endif
171: }
172:
173: /*** sound_endfield - end frame and output sound ***/
174:
175: void sound_endfield(void)
176: {
177: static int oldpos = 0;
178: int pos = voice_get_position(sound_voice);
179: unsigned int blockpos = pos / sound_sampsperfield;
180: int writepos = sound_block*sound_sampsperfield;
181: uint16 *buffer = sound_sample->data + writepos*2*2; /* 16bit, stereo */
182: unsigned int i;
183:
184: /* write into new block */
185: for (i = 0; i < sound_sampsperfield; i++) {
186: buffer[i*2] = ((sint16)soundbuf[0][i]) + 0x8000;
187: buffer[i*2+1] = ((sint16)soundbuf[1][i]) + 0x8000;
188: }
189: if ((oldpos <= writepos && (pos < oldpos || pos > writepos)) ||
190: (oldpos > writepos && (pos > writepos && pos < oldpos))) {
191: /* under-run occured - reset to new sound block */
192: voice_set_position(sound_voice, writepos);
193: sound_feedback = -1;
194: } else {
195: if (blockpos < sound_block) {
196: if ((sound_block - blockpos) < SOUND_THRESHOLD)
197: sound_feedback = -1;
198: else
199: sound_feedback = 0;
200: } else {
201: if ((sound_block - blockpos + sound_blocks) < SOUND_THRESHOLD)
202: sound_feedback = -1;
203: else
204: sound_feedback = 0;
205: }
206: }
207: sound_block++;
208: if (sound_block >= sound_blocks)
209: sound_block = 0;
210: sound_readyblock();
211: oldpos = pos;
212: }
213:
214: void sound_readyblock(void)
215: {
216: static int locked = 0;
217: int writepos = sound_block*sound_sampsperfield;
218: unsigned int a = 0;
219: if (locked && digi_driver->unlock_voice)
220: digi_driver->unlock_voice(sound_voice);
221:
222: while((voice_get_position(sound_voice) /
223: sound_sampsperfield) == sound_block) {
224: usleep(100);
225: a++;
226: if (a > 100000) {
227: LOG_CRITICAL(("Sound error - pos=%d %d=%d",
228: voice_get_position(sound_voice),
229: sound_sampsperfield, sound_block));
230: exit(0);
231: }
232: /* cannot write to the next block until it's played! */
233: }
234: if (digi_driver->lock_voice) {
235: digi_driver->lock_voice(sound_voice, writepos,
236: writepos+sound_sampsperfield);
237: locked = 1;
238: }
239: }
240:
241: #ifdef JFM
242:
243: /*** sound_ym2612fetch - fetch byte from ym2612 chip ***/
244:
245: uint8 sound_ym2612fetch(uint8 addr)
246: {
247: return jfm_read(sound_ctx, addr);
248: }
249:
250: /*** sound_ym2612store - store a byte to the ym2612 chip ***/
251:
252: void sound_ym2612store(uint8 addr, uint8 data)
253: {
254: jfm_write(sound_ctx, addr, data);
255: }
256:
257: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.