|
|
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: #ifdef JFM
19: # include "jfm.h"
20: #else
21: # include "support.h"
22: # include "fm.h"
23: #endif
24:
25: #include <sys/soundcard.h>
26:
27: #define SOUND_DEVICE "/dev/dsp"
28:
29: /*** variables externed ***/
30:
31: /*** forward references ***/
32:
33: /*** file scoped variables ***/
34:
35: static int soundp_dev = -1;
36: static int soundp_format;
37: static int soundp_stereo;
38: static int soundp_frag;
39: static int soundp_fragsize;
40: static unsigned int soundp_speed;
41:
42: #ifdef JFM
43: static t_jfm_ctx *sound_ctx;
44: #endif
45:
46: /*** soundp_start - start sound hardware ***/
47:
48: int soundp_start(void)
49: {
50: audio_buf_info sound_info;
51:
52: if ((soundp_dev = open(SOUND_DEVICE, O_WRONLY, 0)) == -1) {
53: LOG_CRITICAL(("open " SOUND_DEVICE " failed: %s", strerror(errno)));
54: return 1;
55: }
56: soundp_frag = (sound_maxfields << 16 |
57: (int)(ceil(log10(sound_sampsperfield * 4) / log10(2))));
58: if (ioctl(soundp_dev, SNDCTL_DSP_SETFRAGMENT, &soundp_frag) == -1) {
59: LOG_CRITICAL(("Error setting fragment size: %s", strerror(errno)));
60: close(soundp_dev);
61: return 1;
62: }
63: soundp_format = AFMT_S16_LE;
64: if (ioctl(soundp_dev, SNDCTL_DSP_SETFMT, &soundp_format) == -1) {
65: LOG_CRITICAL(("Error setting sound device format: %s", strerror(errno)));
66: close(soundp_dev);
67: return 1;
68: }
69: if (soundp_format != AFMT_S16_LE && soundp_format != AFMT_S16_BE) {
70: LOG_CRITICAL(("Sound device format not supported (must be 16 bit)"));
71: close(soundp_dev);
72: return 1;
73: }
74: soundp_stereo = 1;
75: if (ioctl(soundp_dev, SNDCTL_DSP_STEREO, &soundp_stereo) == -1) {
76: LOG_CRITICAL(("Error setting stereo: %s", strerror(errno)));
77: close(soundp_dev);
78: return 1;
79: }
80: if (soundp_stereo != 1) {
81: LOG_CRITICAL(("Sound device does not support stereo"));
82: close(soundp_dev);
83: return 1;
84: }
85: soundp_speed = sound_speed;
86: if (ioctl(soundp_dev, SNDCTL_DSP_SPEED, &soundp_speed) == -1) {
87: LOG_CRITICAL(("Error setting sound speed: %s", strerror(errno)));
88: close(soundp_dev);
89: return 1;
90: }
91: if (soundp_speed != sound_speed) {
92: if (abs(soundp_speed - sound_speed) < 100) {
93: LOG_NORMAL(("Warning: Sample rate not exactly 22050"));
94: } else {
95: LOG_CRITICAL(("Sound device does not support sample rate %d "
96: "(returned %d)", sound_speed, soundp_speed));
97: close(soundp_dev);
98: return 1;
99: }
100: }
101: if (ioctl(soundp_dev, SNDCTL_DSP_GETOSPACE, &sound_info) == -1) {
102: LOG_CRITICAL(("Error getting output space info", strerror(errno)));
103: close(soundp_dev);
104: return 1;
105: }
106: LOG_VERBOSE(("Total allocated fragments = %d (requested %d)",
107: sound_info.fragstotal, sound_maxfields));
108: LOG_VERBOSE(("Fragment size = %d (requested %d)", sound_info.fragsize,
109: sound_sampsperfield * 4));
110: LOG_VERBOSE(("Bytes free in buffer = %d", sound_info.bytes));
111: LOG_VERBOSE(("Theshold = %d bytes (%d fields of sound === %dms latency)",
112: sound_threshold * 4, sound_minfields,
113: (int)(1000 * (float)sound_minfields / (float)vdp_framerate)));
114: if ((signed)sound_threshold >= sound_info.bytes) {
115: LOG_CRITICAL(("Threshold exceeds bytes free in buffer"));
116: close(soundp_dev);
117: return 1;
118: }
119: return 0;
120: }
121:
122: /*** soundp_stop - stop sound hardware ***/
123:
124: void soundp_stop(void)
125: {
126: if (soundp_dev != -1)
127: close(soundp_dev);
128: soundp_dev = -1;
129: }
130:
131: /*** sound_samplesbuffered - how many samples are currently buffered? ***/
132:
133: int soundp_samplesbuffered(void)
134: {
135: audio_buf_info sound_info;
136: int pending;
137:
138: if (ioctl(soundp_dev, SNDCTL_DSP_GETOSPACE, &sound_info) == -1) {
139: LOG_CRITICAL(("Error getting output space info: %s", strerror(errno)));
140: return -1;
141: }
142: pending = (sound_info.fragstotal * sound_info.fragsize) - sound_info.bytes;
143: return (pending / 4); /* 2 bytes per sample, 2 channel stereo */
144: }
145:
146: void soundp_output(uint16 *left, uint16 *right, unsigned int samples)
147: {
148: uint16 buffer[(SOUND_MAXRATE / 50) * 2]; /* pal is slowest framerate */
149: #ifdef WORDS_BIGENDIAN
150: int endian = 1;
151: #else
152: int endian = 0;
153: #endif
154: unsigned int i;
155:
156: if (samples > (sizeof(buffer) << 1)) {
157: /* we only bother with coping with one fields worth of samples */
158: LOG_CRITICAL(("Too many samples passed to soundp_output!"));
159: return;
160: }
161: if (soundp_format == AFMT_S16_LE && endian == 0) {
162: /* device matches endianness of host */
163: for (i = 0; i < samples; i++) {
164: buffer[i * 2] = left[i];
165: buffer[i * 2 + 1] = right[i];
166: }
167: } else {
168: /* device is odd and is different to host endianness */
169: for (i = 0; i < samples; i++) {
170: buffer[i * 2] = ((left[i] >> 8) | ((left[i] << 8) & 0xff00));
171: buffer[i * 2 + 1] = ((right[i] >> 8) | ((right[i] << 8) & 0xff00));
172: }
173: }
174: if (write(soundp_dev, buffer, samples * 4) == -1) {
175: if (errno != EINTR)
176: LOG_CRITICAL(("Error writing to sound device: %s", strerror(errno)));
177: }
178: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.