FreeWRL / FreeX3D 4.3.0
wavmaker.c
1
2/****************************************************************************
3 This file is part of the FreeWRL/FreeX3D Distribution.
4
5 Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
6
7 FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
8 it under the terms of the GNU Lesser Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 FreeWRL/FreeX3D is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
19****************************************************************************/
20
21
22# include <config.h>
23
24#include "system.h"
25#include "soundheader.h"
26
27
28int dspFile = -1; /* Sound output device*/
29char *dspBlock = NULL; /* a block to send*/
30
31/* Fragment parameters*/
32int readSize; /* how much to read from wav file - either BUFSIZE or less*/
33
34/* are we playing a sound?*/
35int DSPplaying = -1;
36
37/* How many bytes have been used since the last cycle?*/
38int bytesPerCycle = 0;
39
40/* how many bytes can we write to the sound card assuming no sound playing?*/
41int soundcardBufferEmptySize = 0;
42int soundcardBufferCurrentSize = 0;
43
44/* DSP parameters, should match sox call parameters.*/
45int SystemBPSample = 16;
46int MaxChannels = 2;
47long int Rate = 22050;
48
49
50/* where the data gets munged to.*/
51short int CombiningBuffer[MAXBUFSIZE];
52void initializeCombiningBuffer();
53
54void playWavFragment() {
55 /* SNDFILE *wavfile, int source) {*/
56 audio_buf_info leftover;
57 int mydata; /* DSP buffer size... used to keep data flowing*/
58
59 /* Only write if there is the need to write data. - dont want*/
60 /* to buffer too much; want sound to be responsive but smooth*/
61 /* -- this call tells us how much room there is.*/
62
63
64 /* Find out how much data was processed by the sound card since the*/
65 /* last write. First time through we assume that the sound card*/
66 /* buffer is flushed, and that we have to write data.*/
67
68 /* printf ("start of playWavFragment source %d\n",source);*/
69 /* */
70
71 /* is the dspFile open? Maybe it failed on open??*/
72 if (dspFile == -1) {
73 /* printf ("dsp not open\n");*/
74 return;
75 }
76
77 if (DSPplaying != 0) {
78 /* first time through*/
79 /* printf ("first time through\n");*/
80 DSPplaying = 0;
81 mydata = 0;
82 readSize = 0;
83 bytesPerCycle = MAXBUFSIZE/2; /* make an assumption.*/
84 } else {
85 /* we have done this before since the file open...*/
86 mydata = soundcardBufferEmptySize - soundcardBufferCurrentSize;
87 /* printf ("SCES %d SCCS %d mydata %d bytes_remaining %ld\n",*/
88 /* soundcardBufferEmptySize,*/
89 /* soundcardBufferCurrentSize,mydata,wavfile->bytes_remaining);*/
90
91
92 /* lets try some scaling here.*/
93 /* did we (or are we close to) running out of data?*/
94 /*if ((mydata <= 0x4ff) && (bytesPerCycle < BUFSIZE*16)) {
95 //printf ("increasing bps\n");
96 bytesPerCycle += 0x100;
97 }*/
98 }
99 /* printf ("md %d, bps %d rate %f bytes/sec\n",mydata, bytesPerCycle, fps*bytesPerCycle);*/
100
101 /* Should we read and write?*/
102 if (mydata <= (bytesPerCycle*2)) {
103 initializeCombiningBuffer();
104 /* printf ("icb, smd %d\n",bytesPerCycle);*/
105 streamMoreData(bytesPerCycle);
106 }
107
108 if (ioctl(dspFile, SNDCTL_DSP_GETOSPACE,&leftover) <0) {
109 printf ("error, SNDCTL_DSP_GETOSPACE\n");
110 dspFile = -1;
111 }
112 /* printf ("space leftover is %d\n",leftover.bytes);*/
113 soundcardBufferCurrentSize = leftover.bytes;
114}
115
116
117
118/* WAV file header read in, lets get the rest of the data ready.*/
119SNDFILE *initiateWAVSound (SNDFILE *wavfile,int mynumber) {
120 wavfile->type=WAVFILE;
121 return wavfile;
122}
123
124/* Close the DSP, release memory.*/
125void closeDSP () {
126 if (dspBlock!=NULL) free(dspBlock);
127 if (dspFile>=0) close(dspFile);
128 dspFile = -1;
129 DSPplaying = -1;
130}
131
132void initiateDSP() {
133 int i;
134 audio_buf_info leftover;
135
136 if ( (dspFile = open("/dev/dsp",O_WRONLY|O_NONBLOCK))
137 /* if ( (dspFile = open("/dev/dsp",O_NDELAY))*/
138 == -1 ) {
139 printf ("FreeWRL::SoundEngine::open /dev/dsp problem (is something else using it?)\n");
140 dspFile=-1;
141 return;
142 }
143
144 i = (N_FRAGMENTS<<16) | FRAG_SIZE;
145 if ( ioctl(dspFile, SNDCTL_DSP_SETFRAGMENT,
146 &i) == -1 ) {
147 printf("ioctl set fragment problem\n");
148 dspFile=-1;
149 return ;
150 }
151
152 /* quick calculation to find out how much space the DRIVER thinks*/
153 /* we have when the sound card buffer is empty.*/
154 if (ioctl(dspFile, SNDCTL_DSP_GETOSPACE,&leftover) <0) {
155 printf ("error, SNDCTL_DSP_GETOSPACE\n");
156 dspFile = -1;
157 }
158 soundcardBufferEmptySize = leftover.bytes;
159 /* printf ("can write a possible amount of %d bytes\n",leftover.bytes);*/
160
161 /* set for 16 bit samples.*/
162 if (ioctl(dspFile,SNDCTL_DSP_SETFMT,&SystemBPSample)<0) {
163 printf ("unable to set DSP bit size to %d\n",SystemBPSample);
164 dspFile = -1; /* flag an error*/
165 }
166
167 /* set for stereo.*/
168 if (ioctl(dspFile,SNDCTL_DSP_STEREO,&MaxChannels)<0) {
169 printf ("unable to set mono/stereo mode to %d\n",MaxChannels);
170 dspFile = -1; /* flag an error*/
171 }
172
173 /* Set rate.*/
174 if (ioctl(dspFile,SNDCTL_DSP_SPEED,&Rate)<0) {
175 printf ("unable to set DSP sampling rate to %ld\n",Rate);
176 dspFile = -1; /* flag an error*/
177 }
178
179
180 return ;
181}
182
183
184void initializeCombiningBuffer() {
185 int count;
186
187 for (count =0; count < MAXBUFSIZE; count++) {
188 /* CombiningBuffer[count] = 32767;*/
189 CombiningBuffer[count] = 0;
190 /* printf ("initialized %d\n",CombiningBuffer[count]);*/
191 }
192}
193
194/* add this new stream to our standard buffer. Convert as appropriate.*/
195void addToCombiningBuffer(int source,int readSize, int offset) {
196 int tc;
197 short int *siptr;
198 int tmp;
199 int ampl;
200 int lbal, rbal;
201
202
203 /* printf ("afer start, offset = %d readSize %d \n", offset,readSize);*/
204
205 ampl = 100 - (sndfile[source]->ampl);
206 if (ampl < 1) ampl = 1; /* stops divide by zero errors*/
207
208 switch (sndfile[source]->FormatChunk.wBitsPerSample) {
209 case SIXTEEN: {
210 siptr = (short int *)(sndfile[source]->data);
211 lbal = sndfile[source]->balance;
212 rbal = 100 - lbal;
213
214 /* lets try this... basically, either add to or*/
215 /* reduce balance, but keep average at 1.0*/
216 rbal = rbal*2;
217 lbal = lbal*2;
218
219 /* printf ("lbal %d rbal %d\n",lbal, rbal);*/
220
221 for (tc=0; tc<(readSize/2); tc++) {
222 /* get value, and adjust for volume*/
223 if ((tc & 0x01) == 0) {
224 /* printf ("left\n");*/
225 tmp = *siptr;
226 tmp = (tmp *100)/ampl;
227 tmp = (tmp * lbal) / 50;
228 tmp = tmp/100;
229 /* balance*/
230 } else {
231 /* printf ("right\n");*/
232 tmp = *siptr;
233 tmp = (tmp *100)/ampl;
234 tmp = (tmp * rbal) / 50;
235 tmp = tmp/100;
236 }
237
238 /* combine them, then check for overflow*/
239 tmp = tmp + (int)CombiningBuffer[offset];
240 if ((tmp > 32767) || (tmp <-32768)) {
241 /* printf ("have a problem, %d\n",tmp);*/
242 if (tmp > 32767) {
243 tmp = 32767;
244 } else {
245 tmp = -32768;
246 }
247 }
248
249 /* CombiningBuffer[offset] += tmp;*/
250 CombiningBuffer[offset] = tmp;
251 offset++;
252 siptr++;
253 }
254 break;
255 }
256
257 default: {
258 printf ("woops, addToStreaming not for this type\n");
259 }
260 }
261}