|
|
1.1 root 1: /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */
2:
3: #include <sys/types.h>
4: #include <sys/stat.h>
5: #include <sys/ioctl.h>
6: #include <unistd.h>
7: #include <fcntl.h>
8: #include <errno.h>
9: #include <string.h>
10: #include <math.h>
1.1.1.2 ! root 11: #include <time.h>
1.1 root 12:
13: #include "generator.h"
14: #include "gensound.h"
15: #include "gensoundp.h"
16: #include "vdp.h"
17: #include "ui.h"
18:
19: #include <allegro.h>
20:
21: /*** variables externed ***/
22:
23: /*** forward references ***/
24:
25: void sound_readyblock(void);
26:
27: /*** file scoped variables ***/
28:
29: static int soundp_format;
30: static int soundp_stereo;
31: static int soundp_frag;
32: static int soundp_fragsize;
33: static unsigned int soundp_speed;
34:
35: static unsigned int soundp_block;
36: static SAMPLE *soundp_sample;
37: static int soundp_voice;
38:
39: #ifdef JFM
40: static t_jfm_ctx *sound_ctx;
41: #endif
42:
43: /*** soundp_start - start sound hardware ***/
44:
45: int soundp_start(void)
46: {
47: unsigned int i;
48: uint16 *p;
49: static int once = 0;
50:
51: if (!once) {
52: once = 1;
53: LOG_VERBOSE(("Initialising sound..."));
54: if (detect_digi_driver(DIGI_AUTODETECT) < 1) {
55: LOG_CRITICAL(("Allegro failed to detect hardware"));
56: return 1;
57: }
58: if (install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL)) {
59: LOG_CRITICAL(("Failed to initialise sound"));
60: return 1;
61: }
62: }
63: /* allocate block capable of holding sound_maxfields frames */
64: if ((soundp_sample = create_sample(16, 1, sound_speed, sound_sampsperfield *
65: sound_maxfields)) == NULL) {
66: LOG_CRITICAL(("Failed to create sample"));
67: return 1;
68: }
69: p = (uint16 *)soundp_sample->data;
70: for (i = 0; i < sound_sampsperfield * sound_maxfields * 2; i--)
71: p[i] = 0x8000;
72: if ((soundp_voice = allocate_voice(soundp_sample)) == -1) {
73: LOG_CRITICAL(("Failed to allocate voice"));
74: destroy_sample(soundp_sample);
75: return 1;
76: }
77: voice_set_playmode(soundp_voice, PLAYMODE_LOOP);
78: voice_set_volume(soundp_voice, 256);
79: voice_set_pan(soundp_voice, 128);
80: voice_set_frequency(soundp_voice, sound_speed);
81: voice_start(soundp_voice);
82: soundp_block = sound_maxfields - 1; /* next block to write to */
83: LOG_VERBOSE(("YM2612 Initialised @ sample rate %d", sound_speed));
84: sound_readyblock();
85: return 0;
86: }
87:
88: /*** soundp_stop - stop sound hardware ***/
89:
90: void soundp_stop(void)
91: {
92: voice_stop(soundp_voice);
93: deallocate_voice(soundp_voice);
94: destroy_sample(soundp_sample);
95: }
96:
97: /*** soundp_samplesbuffered - how many samples are currently buffered? ***/
98:
99: int soundp_samplesbuffered(void)
100: {
101: int pos = voice_get_position(soundp_voice);
102: unsigned int blockpos = pos / sound_sampsperfield;
103: int pending;
104:
105: if (blockpos == soundp_block) /* erk, playing in the write block */
106: pending = 0;
107: else if (blockpos < soundp_block)
108: pending = soundp_block - blockpos;
109: else
110: pending = soundp_block + sound_maxfields - blockpos;
111: if (pending) /* quantisation means we've over estimated by one, so adjust */
112: pending--;
113: return (pending * sound_sampsperfield);
114: }
115:
116: void soundp_output(uint16 *left, uint16 *right, unsigned int samples)
117: {
118: int writepos = soundp_block * sound_sampsperfield;
119: uint16 *buffer = soundp_sample->data + writepos * 2 * 2; /* 16bit, stereo */
120: unsigned int i;
121:
122: if (samples != sound_sampsperfield) {
123: LOG_CRITICAL(("allegro sound can only be used in field blocks"));
124: return;
125: }
126: /* write into new block */
127: for (i = 0; i < samples; i++) {
128: buffer[i * 2] = ((sint16)left[i]) + 0x8000;
129: buffer[i * 2 + 1] = ((sint16)right[i]) + 0x8000;
130: }
131: soundp_block++;
132: if (soundp_block >= sound_maxfields)
133: soundp_block = 0;
134: sound_readyblock();
135: }
136:
137: void sound_readyblock(void)
138: {
139: static int locked = 0;
140: int writepos = soundp_block * sound_sampsperfield;
1.1.1.2 ! root 141: time_t start = time(NULL);
1.1 root 142:
143: if (locked && digi_driver->unlock_voice)
144: digi_driver->unlock_voice(soundp_voice);
145:
146: while ((voice_get_position(soundp_voice) /
147: sound_sampsperfield) == soundp_block) {
1.1.1.2 ! root 148: /* I used to usleep here, but it breaks on some platforms - then I
! 149: tried uclock() which failed too, so we're just going to busywait */
! 150: if (time(NULL) > start + 10) {
1.1 root 151: LOG_CRITICAL(("Sound error - pos=%d %d=%d",
152: voice_get_position(soundp_voice),
153: sound_sampsperfield, soundp_block));
154: exit(0);
155: }
156: /* cannot write to the next block until it's played! */
157: }
158: if (digi_driver->lock_voice) {
159: digi_driver->lock_voice(soundp_voice, writepos,
160: writepos + sound_sampsperfield);
161: locked = 1;
162: }
163: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.