1 /*
2  *  SID_hp.i - 6581 emulation, HP-UX specific stuff
3  *
4  *  Lutz Vieweg <lkv@mania.robin.de>
5  */
6 
7 extern "C" {
8 	#include <sys/audio.h>
9 	#include <unistd.h>
10 	#include <fcntl.h>
11 	#include <sys/ioctl.h>
12 }
13 
14 #define TXBUFSIZE  16384 // bytes, not samples
15 #define TXFRAGSIZE 1024  // samples, not bytes
16 #define TXLOWWATER (TXBUFSIZE-(TXFRAGSIZE*2)) // bytes, not samples
17 
18 /*
19  *  Initialization
20  */
21 
init_sound(void)22 void DigitalRenderer::init_sound(void)
23 {
24 	ready = false;
25 
26 	if ((fd = open("/dev/audio", O_WRONLY | O_NDELAY, 0)) < 0) {
27 		fprintf(stderr, "unable to open /dev/audio -> no sound\n");
28 		return;
29 	}
30 
31 	int flags;
32 	if ((flags = fcntl (fd, F_GETFL, 0)) < 0) {
33 		fprintf(stderr, "unable to set non-blocking mode for /dev/audio -> no sound\n");
34 		return;
35 	}
36 	flags |= O_NDELAY;
37 	if (fcntl (fd, F_SETFL, flags) < 0) {
38 		fprintf(stderr, "unable to set non-blocking mode for /dev/audio -> no sound\n");
39 		return;
40 	}
41 
42 	if (ioctl(fd, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_LINEAR16BIT)) {
43 		fprintf(stderr, "unable to select 16bit-linear sample format -> no sound\n");
44 		return;
45 	}
46 
47 	if (ioctl(fd, AUDIO_SET_SAMPLE_RATE, 44100)) {
48 		fprintf(stderr, "unable to select 44.1kHz sample-rate -> no sound\n");
49 		return;
50 	}
51 
52 	if (ioctl(fd, AUDIO_SET_CHANNELS, 1)) {
53 		fprintf(stderr, "unable to select 1-channel playback -> no sound\n");
54 		return;
55 	}
56 
57 	// choose between:
58 	// AUDIO_OUT_SPEAKER
59 	// AUDIO_OUT_HEADPHONE
60 	// AUDIO_OUT_LINE
61 	if (ioctl(fd, AUDIO_SET_OUTPUT, AUDIO_OUT_SPEAKER)) {
62 		fprintf(stderr, "unable to select audio output -> no sound\n");
63 		return;
64 	}
65 
66 	{
67 		// set volume:
68 		audio_describe description;
69 		audio_gains gains;
70 		if (ioctl(fd, AUDIO_DESCRIBE, &description)) {
71 			fprintf(stderr, "unable to get audio description -> no sound\n");
72 			return;
73 		}
74 		if (ioctl (fd, AUDIO_GET_GAINS, &gains)) {
75 			fprintf(stderr, "unable to get gain values -> no sound\n");
76 			return;
77 		}
78 
79 		float volume = 1.0;
80 		gains.transmit_gain = (int)((float)description.min_transmit_gain +
81                                   (float)(description.max_transmit_gain
82                                           - description.min_transmit_gain)
83                                           * volume);
84 		if (ioctl (fd, AUDIO_SET_GAINS, &gains)) {
85 			fprintf(stderr, "unable to set gain values -> no sound\n");
86 			return;
87 		}
88 	}
89 
90 	if (ioctl(fd, AUDIO_SET_TXBUFSIZE, TXBUFSIZE)) {
91 		fprintf(stderr, "unable to set transmission buffer size -> no sound\n");
92 		return;
93 	}
94 
95 	sound_calc_buf = new int16[TXFRAGSIZE];
96 
97 	linecnt = 0;
98 
99 	ready = true;
100 	return;
101 }
102 
103 
104 /*
105  *  Destructor
106  */
107 
~DigitalRenderer()108 DigitalRenderer::~DigitalRenderer()
109 {
110 	if (fd > 0) {
111 		if (ready) {
112 			ioctl(fd, AUDIO_DRAIN);
113 		}
114 		ioctl(fd, AUDIO_RESET);
115 		close(fd);
116 	}
117 }
118 
119 
120 /*
121  *  Pause sound output
122  */
123 
Pause(void)124 void DigitalRenderer::Pause(void)
125 {
126 }
127 
128 
129 /*
130  * Resume sound output
131  */
132 
Resume(void)133 void DigitalRenderer::Resume(void)
134 {
135 }
136 
137 
138 /*
139  *  Fill buffer, sample volume (for sampled voice)
140  */
141 
EmulateLine(void)142 void DigitalRenderer::EmulateLine(void)
143 {
144 	sample_buf[sample_in_ptr] = volume;
145 	sample_in_ptr = (sample_in_ptr + 1) % SAMPLE_BUF_SIZE;
146 
147 	// testing the audio status at each raster-line is
148 	// really not necessary. Let's do it every 50th one..
149 	// ought to be enough by far.
150 
151 	linecnt--;
152 	if (linecnt < 0 && ready) {
153 		linecnt = 50;
154 
155 		// check whether we should add some more data to the
156 		// transmission buffer.
157 
158 		if (ioctl(fd, AUDIO_GET_STATUS, &status)) {
159 			fprintf(stderr,"fatal: unable to get audio status\n");
160 			exit(20);
161 		}
162 
163 		if (status.transmit_buffer_count < TXLOWWATER) {
164 			// add one sound fragment..
165 			calc_buffer(sound_calc_buf, TXFRAGSIZE*2);
166 
167 			// since we've checked for enough space in the transmission buffer,
168 			// it is an error if the non-blocking write returns anything but
169 			// TXFRAGSIZE*2
170 			if (TXFRAGSIZE*2 != write (fd, sound_calc_buf, TXFRAGSIZE*2)) {
171 				fprintf(stderr,"fatal: write to audio-device failed\n");
172 				exit(20);
173 			}
174 		}
175 	}
176 }
177 
178