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