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