FreeWRL/FreeX3D  3.0.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 
28 int dspFile = -1; /* Sound output device*/
29 char *dspBlock = NULL; /* a block to send*/
30 
31 /* Fragment parameters*/
32 int readSize; /* how much to read from wav file - either BUFSIZE or less*/
33 
34 /* are we playing a sound?*/
35 int DSPplaying = -1;
36 
37 /* How many bytes have been used since the last cycle?*/
38 int bytesPerCycle = 0;
39 
40 /* how many bytes can we write to the sound card assuming no sound playing?*/
41 int soundcardBufferEmptySize = 0;
42 int soundcardBufferCurrentSize = 0;
43 
44 /* DSP parameters, should match sox call parameters.*/
45 int SystemBPSample = 16;
46 int MaxChannels = 2;
47 long int Rate = 22050;
48 
49 
50 /* where the data gets munged to.*/
51 short int CombiningBuffer[MAXBUFSIZE];
52 void initializeCombiningBuffer();
53 
54 void 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.*/
119 SNDFILE *initiateWAVSound (SNDFILE *wavfile,int mynumber) {
120  wavfile->type=WAVFILE;
121  return wavfile;
122 }
123 
124 /* Close the DSP, release memory.*/
125 void closeDSP () {
126  if (dspBlock!=NULL) free(dspBlock);
127  if (dspFile>=0) close(dspFile);
128  dspFile = -1;
129  DSPplaying = -1;
130 }
131 
132 void 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 
184 void 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.*/
195 void 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 }