audio.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. /* $Id$
  2. * MegaZeux
  3. *
  4. * Copyright (C) 2004 Gilead Kutnick
  5. * Copyright (C) 2004 madbrain
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program 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 GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21. // Code to handle module playing, sample playing, and PC speaker
  22. // sfx emulation.
  23. #include <math.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <sys/stat.h>
  27. #include "audio.h"
  28. #include "modplug.h"
  29. #include "libmodplug/stdafx.h"
  30. #include "libmodplug/sndfile.h"
  31. #include "SDL.h"
  32. #include "sfx.h"
  33. #include "data.h"
  34. #include "configure.h"
  35. #include "gdm2s3m.h"
  36. #include "fsafeopen.h"
  37. #include "delay.h"
  38. struct _ModPlugFile
  39. {
  40. CSoundFile mSoundFile;
  41. };
  42. audio_struct audio;
  43. int error_mode;
  44. // An update should happen every 2ms, so this many samples
  45. const double pc_speaker_interval = 44100 / 500;
  46. const int freq_conversion = 3579364;
  47. void audio_callback(void *userdata, Uint8 *stream, int len)
  48. {
  49. int i, i2, offset = 0;
  50. Sint16 *mix_src_ptr;
  51. Sint32 *mix_dest_ptr;
  52. Sint32 *buffer_src_ptr;
  53. Sint16 *buffer_dest_ptr;
  54. Sint32 cur_sample;
  55. int sample_duration, end_duration;
  56. int increment_value, increment_buffer;
  57. if(audio.mod_playing && music_on)
  58. {
  59. int read_len =
  60. ModPlug_Read(audio.current_mod, audio.mod_buffer, len);
  61. if(read_len < len)
  62. {
  63. // Reset position
  64. audio.current_mod->mSoundFile.SetCurrentPos(0);
  65. // Read anew remaining bytes
  66. ModPlug_Read(audio.current_mod, audio.mod_buffer + read_len,
  67. len - read_len);
  68. }
  69. }
  70. else
  71. {
  72. memset(audio.mod_buffer, 0, len);
  73. }
  74. mix_dest_ptr = audio.mix_buffer;
  75. mix_src_ptr = audio.mod_buffer;
  76. for(i = 0; i < len / 2; i++)
  77. {
  78. *mix_dest_ptr = *mix_src_ptr;
  79. mix_dest_ptr++;
  80. mix_src_ptr++;
  81. }
  82. // Mix PC speaker effect. First get whatever ran over from last time.
  83. mix_dest_ptr = audio.mix_buffer;
  84. sample_duration = audio.pc_speaker_last_duration;
  85. if(sample_duration >= len / 4)
  86. {
  87. end_duration = len / 4;
  88. audio.pc_speaker_last_duration = sample_duration - end_duration;
  89. sample_duration = end_duration;
  90. }
  91. if(audio.pc_speaker_last_playing)
  92. {
  93. increment_value =
  94. (int)((double)audio.pc_speaker_last_frequency / 44100.0 * 4294967296.0);
  95. increment_buffer = audio.pc_speaker_last_increment_buffer;
  96. for(i = 0; i < sample_duration; i++)
  97. {
  98. cur_sample = (Uint32)((increment_buffer & 0x80000000) >> 18) - 4096;
  99. *mix_dest_ptr += cur_sample;
  100. *(mix_dest_ptr + 1) += cur_sample;
  101. increment_buffer += increment_value;
  102. mix_dest_ptr += 2;
  103. }
  104. audio.pc_speaker_last_increment_buffer = increment_buffer;
  105. }
  106. else
  107. {
  108. mix_dest_ptr += (sample_duration * 2);
  109. }
  110. offset += sample_duration;
  111. if(offset < len / 4)
  112. audio.pc_speaker_last_playing = 0;
  113. while(offset < len / 4)
  114. {
  115. sound_system();
  116. sample_duration = (int)(pc_speaker_interval * audio.pc_speaker_note_duration);
  117. if(offset + sample_duration >= len / 4)
  118. {
  119. end_duration = (len / 4) - offset;
  120. audio.pc_speaker_last_duration = sample_duration - end_duration;
  121. audio.pc_speaker_last_playing = audio.pc_speaker_playing;
  122. audio.pc_speaker_last_frequency = audio.pc_speaker_frequency;
  123. sample_duration = end_duration;
  124. }
  125. offset += sample_duration;
  126. if(audio.pc_speaker_playing)
  127. {
  128. increment_value =
  129. (int)((double)audio.pc_speaker_frequency / 44100.0 * 4294967296.0);
  130. increment_buffer = 0;
  131. for(i = 0; i < sample_duration; i++)
  132. {
  133. cur_sample = (Uint32)((increment_buffer & 0x80000000) >> 18) - 4096;
  134. *mix_dest_ptr += cur_sample;
  135. *(mix_dest_ptr + 1) += cur_sample;
  136. increment_buffer += increment_value;
  137. mix_dest_ptr += 2;
  138. }
  139. audio.pc_speaker_last_increment_buffer = increment_buffer;
  140. }
  141. else
  142. {
  143. mix_dest_ptr += (sample_duration * 2);
  144. }
  145. }
  146. // Mix samples, if any are playing
  147. if(audio.num_samples_playing && music_on)
  148. {
  149. for(i = 0; i < 16; i++)
  150. {
  151. if(audio.samples_playing[i])
  152. {
  153. int read_len =
  154. ModPlug_Read(audio.samples_playing[i], audio.sample_buffers[i], len);
  155. mix_src_ptr = audio.sample_buffers[i];
  156. mix_dest_ptr = audio.mix_buffer;
  157. for(i2 = 0; i2 < read_len / 2; i2++)
  158. {
  159. *mix_dest_ptr += *mix_src_ptr;
  160. mix_src_ptr++;
  161. mix_dest_ptr++;
  162. }
  163. // If a full read wasn't done the sample's play is up, so destroy it
  164. if(read_len < len)
  165. end_individual_sample(i);
  166. }
  167. }
  168. }
  169. buffer_src_ptr = audio.mix_buffer;
  170. buffer_dest_ptr = (Sint16 *)stream;
  171. for(i = 0; i < len / 2; i++)
  172. {
  173. cur_sample = *buffer_src_ptr;
  174. if(cur_sample > 32767)
  175. cur_sample = 32767;
  176. if(cur_sample < -32768)
  177. cur_sample = -32768;
  178. *buffer_dest_ptr = cur_sample;
  179. buffer_src_ptr++;
  180. buffer_dest_ptr++;
  181. }
  182. }
  183. void init_audio(config_info *conf)
  184. {
  185. int buffer_size = conf->buffer_size;
  186. SDL_AudioSpec desired_spec =
  187. {
  188. 44100,
  189. AUDIO_S16SYS,
  190. 2,
  191. 0,
  192. buffer_size,
  193. 0,
  194. 0,
  195. audio_callback,
  196. NULL
  197. };
  198. if(conf->oversampling_on)
  199. {
  200. audio.mod_settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING;
  201. }
  202. audio.mod_settings.mFrequency = 44100;
  203. audio.mod_settings.mChannels = 2;
  204. audio.mod_settings.mBits = 16;
  205. switch(conf->resampling_mode)
  206. {
  207. case 0:
  208. {
  209. audio.mod_settings.mResamplingMode = MODPLUG_RESAMPLE_NEAREST;
  210. break;
  211. }
  212. case 1:
  213. {
  214. audio.mod_settings.mResamplingMode = MODPLUG_RESAMPLE_LINEAR;
  215. break;
  216. }
  217. case 2:
  218. {
  219. audio.mod_settings.mResamplingMode = MODPLUG_RESAMPLE_SPLINE;
  220. break;
  221. }
  222. case 3:
  223. {
  224. audio.mod_settings.mResamplingMode = MODPLUG_RESAMPLE_FIR;
  225. break;
  226. }
  227. }
  228. audio.mod_settings.mLoopCount = -1;
  229. ModPlug_SetSettings(&audio.mod_settings);
  230. SDL_OpenAudio(&desired_spec, &audio.audio_settings);
  231. audio.mod_buffer = (Sint16 *)malloc(audio.audio_settings.size);
  232. audio.mix_buffer = (Sint32 *)malloc(audio.audio_settings.size * 2);
  233. SDL_PauseAudio(0);
  234. }
  235. void load_mod(char *filename)
  236. {
  237. FILE *input_file;
  238. char *input_buffer;
  239. int file_size;
  240. int extension_pos = strlen(filename) - 4;
  241. char new_file[MAX_PATH];
  242. if(extension_pos && !strcasecmp(filename + extension_pos, ".gdm"))
  243. {
  244. char translated_filename_src[MAX_PATH];
  245. char translated_filename_dest[MAX_PATH];
  246. // GDM -> S3M
  247. strcpy(new_file, filename);
  248. memcpy(new_file + extension_pos, ".s3m", 4);
  249. fsafetranslate(filename, translated_filename_src);
  250. if(fsafetranslate(new_file, translated_filename_dest) < 0)
  251. {
  252. // If it doesn't exist, create it by converting.
  253. convert_gdm_s3m(translated_filename_src, new_file);
  254. }
  255. filename = new_file;
  256. }
  257. if(audio.mod_playing)
  258. end_mod();
  259. input_file = fsafeopen(filename, "rb");
  260. if(input_file)
  261. {
  262. file_size = filelength(input_file);
  263. input_buffer = (char *)malloc(file_size);
  264. fread(input_buffer, file_size, 1, input_file);
  265. audio.current_mod = ModPlug_Load(input_buffer, file_size);
  266. if(audio.current_mod)
  267. {
  268. audio.mod_playing = 1;
  269. }
  270. free(input_buffer);
  271. }
  272. }
  273. void end_mod(void)
  274. {
  275. if(audio.mod_playing)
  276. {
  277. ModPlug_Unload(audio.current_mod);
  278. audio.mod_playing = 0;
  279. }
  280. }
  281. void play_sample(int freq, char *filename)
  282. {
  283. FILE *input_file;
  284. char *input_buffer;
  285. int file_size;
  286. int extension_pos = strlen(filename) - 4;
  287. char new_file[256];
  288. // FIXME - destroy least recently used?
  289. if(audio.num_samples_playing >= MAX_SAMS)
  290. {
  291. unsigned int smallest = audio.sam_timestamps[0];
  292. int smallest_i = 0;
  293. int i;
  294. for(i = 1; i < MAX_SAMS; i++)
  295. {
  296. if(audio.sam_timestamps[i] < smallest)
  297. {
  298. smallest = audio.sam_timestamps[i];
  299. smallest_i = i;
  300. }
  301. }
  302. end_individual_sample(smallest_i);
  303. }
  304. if(extension_pos && !strcasecmp(filename + extension_pos, ".sam"))
  305. {
  306. char translated_filename_src[MAX_PATH];
  307. char translated_filename_dest[MAX_PATH];
  308. // GDM -> S3M
  309. strcpy(new_file, filename);
  310. memcpy(new_file + extension_pos, ".wav", 4);
  311. fsafetranslate(filename, translated_filename_src);
  312. if(fsafetranslate(new_file, translated_filename_dest) < 0)
  313. {
  314. // If it doesn't exist, create it by converting.
  315. convert_sam_to_wav(translated_filename_src, new_file);
  316. }
  317. filename = new_file;
  318. }
  319. input_file = fsafeopen(filename, "rb");
  320. if(input_file)
  321. {
  322. int i;
  323. ModPlugFile *sample_loaded;
  324. file_size = filelength(input_file);
  325. input_buffer = (char *)malloc(file_size);
  326. fread(input_buffer, file_size, 1, input_file);
  327. sample_loaded = ModPlug_Load(input_buffer, file_size);
  328. if(sample_loaded)
  329. {
  330. // A little hack to modify the pitch
  331. sample_loaded->mSoundFile.Ins[1].nC4Speed = (freq_conversion / freq) / 2;
  332. sample_loaded->mSoundFile.Ins[2].nC4Speed = (freq_conversion / freq) / 2;
  333. sample_loaded->mSoundFile.Ins[1].nVolume = (256 * sound_gvol) / 8;
  334. sample_loaded->mSoundFile.Ins[2].nVolume = (256 * sound_gvol) / 8;
  335. // Find a free position to put it
  336. for(i = 0; i < 16; i++)
  337. {
  338. if(audio.samples_playing[i] == NULL)
  339. break;
  340. }
  341. audio.samples_playing[i] = sample_loaded;
  342. audio.sample_buffers[i] =
  343. (Sint16 *)malloc(audio.audio_settings.size);
  344. audio.num_samples_playing++;
  345. audio.sam_timestamps[i] = get_ticks();
  346. }
  347. free(input_buffer);
  348. fclose(input_file);
  349. }
  350. }
  351. void end_individual_sample(int sam_num)
  352. {
  353. ModPlug_Unload(audio.samples_playing[sam_num]);
  354. free(audio.sample_buffers[sam_num]);
  355. audio.num_samples_playing--;
  356. audio.samples_playing[sam_num] = NULL;
  357. }
  358. void end_sample(void)
  359. {
  360. int i;
  361. for(i = 0; i < 16; i++)
  362. {
  363. if(audio.samples_playing[i])
  364. end_individual_sample(i);
  365. }
  366. }
  367. void jump_mod(int order)
  368. {
  369. if(audio.mod_playing)
  370. audio.current_mod->mSoundFile.SetCurrentOrder(order);
  371. }
  372. int get_order()
  373. {
  374. if(audio.mod_playing)
  375. return audio.current_mod->mSoundFile.GetCurrentOrder();
  376. else
  377. return 0;
  378. }
  379. // FIXME - This may have to be adjusted slightly. It SEEMS that
  380. // playing the module at a volume of 1-128 is suitable.
  381. void volume_mod(int vol)
  382. {
  383. if(audio.mod_playing)
  384. audio.current_mod->mSoundFile.SetMasterVolume((vol * music_gvol / 16) + 1);
  385. }
  386. // FIXME - Implement? The best route right now would be to load a module
  387. // then mangle it so it only plays the given sample at the given frequency.
  388. void spot_sample(int freq, int sample)
  389. {
  390. }
  391. void sound(int frequency, int duration)
  392. {
  393. audio.pc_speaker_playing = 1;
  394. audio.pc_speaker_frequency = frequency;
  395. audio.pc_speaker_note_duration = duration;
  396. }
  397. void nosound(int duration)
  398. {
  399. audio.pc_speaker_playing = 0;
  400. audio.pc_speaker_note_duration = duration;
  401. }
  402. int filelength(FILE *fp)
  403. {
  404. int length;
  405. fseek(fp, 0, SEEK_END);
  406. length = ftell(fp);
  407. fseek(fp, 0, SEEK_SET);
  408. return length;
  409. }
  410. const int default_period = 428;
  411. // Based off of original source by madbrain
  412. void convert_sam_to_wav(char *source_name, char *dest_name)
  413. {
  414. FILE *source, *dest;
  415. int frequency;
  416. int source_length, dest_length;
  417. char *data;
  418. int i;
  419. source = fopen(source_name, "rb");
  420. if(source == NULL)
  421. return;
  422. dest = fopen(dest_name, "wb");
  423. source_length = filelength(source);
  424. frequency = freq_conversion / default_period;
  425. data = (char *)malloc(source_length + 44);
  426. dest_length = source_length - 8;
  427. data[0] = 'R';
  428. data[1] = 'I';
  429. data[2] = 'F';
  430. data[3] = 'F';
  431. data[4] = dest_length & 0xFF;
  432. data[5] = (dest_length >> 8) & 0xFF;
  433. data[6] = (dest_length >> 16) & 0xFF;
  434. data[7] = (dest_length >> 24) & 0xFF;
  435. data[8] = 'W';
  436. data[9] = 'A';
  437. data[10] = 'V';
  438. data[11] = 'E';
  439. data[12] = 'f';
  440. data[13] = 'm';
  441. data[14] = 't';
  442. data[15] = ' ';
  443. data[16] = 16;
  444. data[17] = 0;
  445. data[18] = 0;
  446. data[19] = 0;
  447. data[20] = 1; // pcm
  448. data[21] = 0;
  449. data[22] = 2; // mono
  450. data[23] = 0;
  451. // frequency, bytes/second
  452. data[24] = frequency & 0xFF;
  453. data[25] = (frequency >> 8) & 0xFF;
  454. data[26] = (frequency >> 16) & 0xFF;
  455. data[27] = (frequency >> 24) & 0xFF;
  456. data[28] = frequency & 0xFF;
  457. data[29] = (frequency >> 8) & 0xFF;
  458. data[30] = (frequency >> 16) & 0xFF;
  459. data[31] = (frequency >> 24) & 0xFF;
  460. data[32] = 1; // total bytes/sample
  461. data[33] = 0;
  462. data[34] = 8; // bit depth
  463. data[35] = 0;
  464. data[36] = 'd';
  465. data[37] = 'a';
  466. data[38] = 't';
  467. data[39] = 'a';
  468. // Sample length
  469. data[40] = source_length & 0xFF;
  470. data[41] = (source_length >> 8) & 0xFF;
  471. data[42] = (source_length >> 16) & 0xFF;
  472. data[43] = (source_length >> 24) & 0xFF;
  473. fread(data + 44, source_length, 1, source);
  474. for(i = 44; i <dest_length; i++)
  475. data[i] += 128;
  476. fwrite(data, dest_length, 1, dest);
  477. free(data);
  478. fclose(source);
  479. fclose(dest);
  480. }