Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Sound.cpp
Go to the documentation of this file.
1 /* Project nGenEx
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: nGenEx.lib
6  FILE: Sound.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Abstract sound class
13 */
14 
15 #include "MemDebug.h"
16 #include "Sound.h"
17 #include "SoundCard.h"
18 #include "Wave.h"
19 
20 #include "vorbis/codec.h"
21 #include "vorbis/vorbisfile.h"
22 
23 // +--------------------------------------------------------------------+
24 
26 
27 Sound*
28 Sound::CreateStream(const char* filename)
29 {
30  Sound* sound = 0;
31 
32  if (!filename || !filename[0] || !creator)
33  return sound;
34 
35  int namelen = strlen(filename);
36 
37  if (namelen < 5)
38  return sound;
39 
40  if ((filename[namelen-3] == 'o' || filename[namelen-3] == 'O') &&
41  (filename[namelen-2] == 'g' || filename[namelen-2] == 'G') &&
42  (filename[namelen-1] == 'g' || filename[namelen-1] == 'G')) {
43 
44  return CreateOggStream(filename);
45  }
46 
47  WAVE_HEADER head;
48  WAVE_FMT fmt;
49  WAVE_FACT fact;
50  WAVE_DATA data;
51  WAVEFORMATEX wfex;
52 
53  ZeroMemory(&head, sizeof(head));
54  ZeroMemory(&fmt, sizeof(fmt));
55  ZeroMemory(&fact, sizeof(fact));
56  ZeroMemory(&data, sizeof(data));
57 
58  LPBYTE buf = 0;
59  LPBYTE p = 0;
60  int len = 0;
61 
62  FILE* f;
63  ::fopen_s(&f, filename, "rb");
64 
65  if (f) {
66  fseek(f, 0, SEEK_END);
67  len = ftell(f);
68  fseek(f, 0, SEEK_SET);
69 
70  if (len > 4096) {
71  len = 4096;
72  }
73 
74  buf = new(__FILE__,__LINE__) BYTE[len];
75 
76  if (buf && len)
77  fread(buf, len, 1, f);
78 
79  fclose(f);
80  }
81 
82 
83  if (len > sizeof(head)) {
84  CopyMemory(&head, buf, sizeof(head));
85 
86  if (head.RIFF == MAKEFOURCC('R', 'I', 'F', 'F') &&
87  head.WAVE == MAKEFOURCC('W', 'A', 'V', 'E')) {
88 
89  p = buf + sizeof(WAVE_HEADER);
90 
91  do {
92  DWORD chunk_id = *((LPDWORD) p);
93 
94  switch (chunk_id) {
95  case MAKEFOURCC('f', 'm', 't', ' '):
96  CopyMemory(&fmt, p, sizeof(fmt));
97  p += fmt.chunk_size + 8;
98  break;
99 
100  case MAKEFOURCC('f', 'a', 'c', 't'):
101  CopyMemory(&fact, p, sizeof(fact));
102  p += fact.chunk_size + 8;
103  break;
104 
105  case MAKEFOURCC('s', 'm', 'p', 'l'):
106  CopyMemory(&fact, p, sizeof(fact));
107  p += fact.chunk_size + 8;
108  break;
109 
110  case MAKEFOURCC('d', 'a', 't', 'a'):
111  CopyMemory(&data, p, sizeof(data));
112  p += 8;
113  break;
114 
115  default:
116  delete[] buf;
117  return sound;
118  }
119  }
120  while (data.chunk_size == 0);
121 
122  wfex.wFormatTag = fmt.wFormatTag;
123  wfex.nChannels = fmt.nChannels;
124  wfex.nSamplesPerSec = fmt.nSamplesPerSec;
125  wfex.nAvgBytesPerSec = fmt.nAvgBytesPerSec;
126  wfex.nBlockAlign = fmt.nBlockAlign;
127  wfex.wBitsPerSample = fmt.wBitsPerSample;
128  wfex.cbSize = 0;
129 
130  sound = Create(Sound::STREAMED, &wfex);
131 
132  if (sound) {
133  sound->SetFilename(filename);
134  sound->StreamFile(filename, p - buf);
135  }
136  }
137  }
138 
139  delete[] buf;
140  return sound;
141 }
142 
143 // +--------------------------------------------------------------------+
144 
145 Sound*
146 Sound::CreateOggStream(const char* filename)
147 {
148  Sound* sound = 0;
149 
150  if (!filename || !filename[0] || !creator)
151  return sound;
152 
153  int namelen = strlen(filename);
154 
155  if (namelen < 5)
156  return sound;
157 
158  WAVEFORMATEX wfex;
159  ZeroMemory(&wfex, sizeof(wfex));
160 
161  FILE* f;
162  ::fopen_s(&f, filename, "rb");
163 
164  if (f) {
165  OggVorbis_File* povf = new(__FILE__,__LINE__) OggVorbis_File;
166 
167  if (!povf) {
168  Print("Sound::CreateOggStream(%s) - out of memory!\n", filename);
169  return sound;
170  }
171 
172  ZeroMemory(povf, sizeof(OggVorbis_File));
173 
174  if (ov_open(f, povf, NULL, 0) < 0) {
175  Print("Sound::CreateOggStream(%s) - not an Ogg bitstream\n", filename);
176  delete povf;
177  return sound;
178  }
179 
180  Print("\nOpened Ogg Bitstream '%s'\n", filename);
181  char **ptr=ov_comment(povf,-1)->user_comments;
182  vorbis_info *vi=ov_info(povf,-1);
183  while(*ptr){
184  Print("%s\n", *ptr);
185  ++ptr;
186  }
187 
188  Print("Bitstream is %d channel, %ldHz\n", vi->channels, vi->rate);
189  Print("Decoded length: %ld samples\n",
190  (long)ov_pcm_total(povf,-1));
191  Print("Encoded by: %s\n\n", ov_comment(povf,-1)->vendor);
192 
193  wfex.wFormatTag = WAVE_FORMAT_PCM;
194  wfex.nChannels = vi->channels;
195  wfex.nSamplesPerSec = vi->rate;
196  wfex.nAvgBytesPerSec = vi->channels * vi->rate * 2;
197  wfex.nBlockAlign = vi->channels * 2;
198  wfex.wBitsPerSample = 16;
199  wfex.cbSize = 0;
200 
202  &wfex,
203  sizeof(OggVorbis_File),
204  (LPBYTE) povf);
205 
206  sound->SetFilename(filename);
207  }
208 
209  return sound;
210 }
211 
212 // +--------------------------------------------------------------------+
213 
214 Sound*
215 Sound::Create(DWORD flags, LPWAVEFORMATEX format)
216 {
217  if (creator) return creator->CreateSound(flags, format);
218  else return 0;
219 }
220 
221 Sound*
222 Sound::Create(DWORD flags, LPWAVEFORMATEX format, DWORD len, LPBYTE data)
223 {
224  if (creator) return creator->CreateSound(flags, format, len, data);
225  else return 0;
226 }
227 
228 void
229 Sound::SetListener(const Camera& cam, const Vec3& vel)
230 {
231  if (creator)
232  creator->SetListener(cam, vel);
233 }
234 
235 // +--------------------------------------------------------------------+
236 
238 : status(UNINITIALIZED), volume(0), flags(0), looped(0),
239 velocity(0,0,0), location(0,0,0), sound_check(0)
240 {
241  strcpy_s(filename, "Sound()");
242 }
243 
244 // +--------------------------------------------------------------------+
245 
247 { }
248 
249 // +--------------------------------------------------------------------+
250 
251 void
253 {
254  flags &= ~LOCKED;
255 }
256 
257 // +--------------------------------------------------------------------+
258 
259 void
261 {
262  if (creator)
263  creator->AddSound(this);
264 }
265 
266 // +--------------------------------------------------------------------+
267 
268 void
269 Sound::SetFilename(const char* s)
270 {
271  if (s) {
272  int n = strlen(s);
273 
274  if (n >= 60) {
275  ZeroMemory(filename, sizeof(filename));
276  strcpy_s(filename, "...");
277  strcat_s(filename, s + n - 59);
278  filename[63] = 0;
279  }
280 
281  else {
282  strcpy_s(filename, s);
283  }
284  }
285 }
286