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