libopenmpt_modplug.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. /*
  2. * libopenmpt_modplug.c
  3. * --------------------
  4. * Purpose: libopenmpt emulation of the libmodplug interface
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #ifndef NO_LIBMODPLUG
  10. #ifdef LIBOPENMPT_BUILD_DLL
  11. #undef LIBOPENMPT_BUILD_DLL
  12. #endif
  13. #ifdef _MSC_VER
  14. #ifndef _CRT_SECURE_NO_WARNINGS
  15. #define _CRT_SECURE_NO_WARNINGS
  16. #endif
  17. #endif /* _MSC_VER */
  18. #include <libopenmpt/libopenmpt.h>
  19. #include <limits.h>
  20. #include <math.h>
  21. #include <memory.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #define MODPLUG_BUILD
  26. #ifdef _MSC_VER
  27. #ifdef MPT_BUILD_MSVC_SHARED
  28. #define DLL_EXPORT
  29. #endif /* MPT_BUILD_MSVC_SHARED */
  30. #ifdef MPT_BUILD_MSVC_STATIC
  31. #define MODPLUG_STATIC
  32. #endif /* MPT_BUILD_MSVC_STATIC */
  33. #endif /* _MSC_VER */
  34. #ifdef _MSC_VER
  35. #define LIBOPENMPT_MODPLUG_API
  36. #else /* !_MSC_VER */
  37. #define LIBOPENMPT_MODPLUG_API LIBOPENMPT_API_HELPER_EXPORT
  38. #endif /* _MSC_VER */
  39. #include "libmodplug/modplug.h"
  40. /* from libmodplug/sndfile.h */
  41. /* header is not c clean */
  42. #define MIXING_ATTENUATION 4
  43. #define MOD_TYPE_NONE 0x0
  44. #define MOD_TYPE_MOD 0x1
  45. #define MOD_TYPE_S3M 0x2
  46. #define MOD_TYPE_XM 0x4
  47. #define MOD_TYPE_MED 0x8
  48. #define MOD_TYPE_MTM 0x10
  49. #define MOD_TYPE_IT 0x20
  50. #define MOD_TYPE_669 0x40
  51. #define MOD_TYPE_ULT 0x80
  52. #define MOD_TYPE_STM 0x100
  53. #define MOD_TYPE_FAR 0x200
  54. #define MOD_TYPE_WAV 0x400
  55. #define MOD_TYPE_AMF 0x800
  56. #define MOD_TYPE_AMS 0x1000
  57. #define MOD_TYPE_DSM 0x2000
  58. #define MOD_TYPE_MDL 0x4000
  59. #define MOD_TYPE_OKT 0x8000
  60. #define MOD_TYPE_MID 0x10000
  61. #define MOD_TYPE_DMF 0x20000
  62. #define MOD_TYPE_PTM 0x40000
  63. #define MOD_TYPE_DBM 0x80000
  64. #define MOD_TYPE_MT2 0x100000
  65. #define MOD_TYPE_AMF0 0x200000
  66. #define MOD_TYPE_PSM 0x400000
  67. #define MOD_TYPE_J2B 0x800000
  68. #define MOD_TYPE_ABC 0x1000000
  69. #define MOD_TYPE_PAT 0x2000000
  70. #define MOD_TYPE_UMX 0x80000000 // Fake type
  71. #define BUFFER_COUNT 1024
  72. struct _ModPlugFile {
  73. openmpt_module* mod;
  74. signed short* buf;
  75. signed int* mixerbuf;
  76. char* name;
  77. char* message;
  78. ModPlug_Settings settings;
  79. ModPlugMixerProc mixerproc;
  80. ModPlugNote** patterns;
  81. };
  82. static ModPlug_Settings globalsettings = {
  83. MODPLUG_ENABLE_OVERSAMPLING|MODPLUG_ENABLE_NOISE_REDUCTION,
  84. 2,
  85. 16,
  86. 44100,
  87. MODPLUG_RESAMPLE_LINEAR,
  88. 128,
  89. 256,
  90. 0,
  91. 0,
  92. 0,
  93. 0,
  94. 0,
  95. 0,
  96. 0
  97. };
  98. static int32_t modplugresamplingmode_to_filterlength(int mode)
  99. {
  100. if(mode<0){
  101. return 1;
  102. }
  103. switch(mode){
  104. case MODPLUG_RESAMPLE_NEAREST: return 1; break;
  105. case MODPLUG_RESAMPLE_LINEAR: return 2; break;
  106. case MODPLUG_RESAMPLE_SPLINE: return 4; break;
  107. case MODPLUG_RESAMPLE_FIR: return 8; break;
  108. }
  109. return 8;
  110. }
  111. LIBOPENMPT_MODPLUG_API ModPlugFile* ModPlug_Load(const void* data, int size)
  112. {
  113. ModPlugFile* file = malloc(sizeof(ModPlugFile));
  114. const char* name = NULL;
  115. const char* message = NULL;
  116. if(!file) return NULL;
  117. memset(file,0,sizeof(ModPlugFile));
  118. memcpy(&file->settings,&globalsettings,sizeof(ModPlug_Settings));
  119. file->mod = openmpt_module_create_from_memory2(data,size,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  120. if(!file->mod){
  121. free(file);
  122. return NULL;
  123. }
  124. file->buf = malloc(BUFFER_COUNT*sizeof(signed short)*4);
  125. if(!file->buf){
  126. openmpt_module_destroy(file->mod);
  127. free(file);
  128. return NULL;
  129. }
  130. openmpt_module_set_repeat_count(file->mod,file->settings.mLoopCount);
  131. name = openmpt_module_get_metadata(file->mod,"title");
  132. if(name){
  133. file->name = malloc(strlen(name)+1);
  134. if(file->name){
  135. strcpy(file->name,name);
  136. }
  137. openmpt_free_string(name);
  138. name = NULL;
  139. }else{
  140. file->name = malloc(strlen("")+1);
  141. if(file->name){
  142. strcpy(file->name,"");
  143. }
  144. }
  145. message = openmpt_module_get_metadata(file->mod,"message");
  146. if(message){
  147. file->message = malloc(strlen(message)+1);
  148. if(file->message){
  149. strcpy(file->message,message);
  150. }
  151. openmpt_free_string(message);
  152. message = NULL;
  153. }else{
  154. file->message = malloc(strlen("")+1);
  155. if(file->message){
  156. strcpy(file->message,"");
  157. }
  158. }
  159. openmpt_module_set_render_param(file->mod,OPENMPT_MODULE_RENDER_STEREOSEPARATION_PERCENT,file->settings.mStereoSeparation*100/128);
  160. openmpt_module_set_render_param(file->mod,OPENMPT_MODULE_RENDER_INTERPOLATIONFILTER_LENGTH,modplugresamplingmode_to_filterlength(file->settings.mResamplingMode));
  161. return file;
  162. }
  163. LIBOPENMPT_MODPLUG_API void ModPlug_Unload(ModPlugFile* file)
  164. {
  165. int p;
  166. if(!file) return;
  167. if(file->patterns){
  168. for(p=0;p<openmpt_module_get_num_patterns(file->mod);p++){
  169. if(file->patterns[p]){
  170. free(file->patterns[p]);
  171. file->patterns[p] = NULL;
  172. }
  173. }
  174. free(file->patterns);
  175. file->patterns = NULL;
  176. }
  177. if(file->mixerbuf){
  178. free(file->mixerbuf);
  179. file->mixerbuf = NULL;
  180. }
  181. openmpt_module_destroy(file->mod);
  182. file->mod = NULL;
  183. free(file->name);
  184. file->name = NULL;
  185. free(file->message);
  186. file->message = NULL;
  187. free(file->buf);
  188. file->buf = NULL;
  189. free(file);
  190. }
  191. LIBOPENMPT_MODPLUG_API int ModPlug_Read(ModPlugFile* file, void* buffer, int size)
  192. {
  193. int framesize;
  194. int framecount;
  195. int frames;
  196. int rendered;
  197. int frame;
  198. int channel;
  199. int totalrendered;
  200. signed short* in;
  201. signed int* mixbuf;
  202. unsigned char* buf8;
  203. signed short* buf16;
  204. signed int* buf32;
  205. if(!file) return 0;
  206. framesize = file->settings.mBits/8*file->settings.mChannels;
  207. framecount = size/framesize;
  208. buf8 = buffer;
  209. buf16 = buffer;
  210. buf32 = buffer;
  211. totalrendered = 0;
  212. while(framecount>0){
  213. frames = framecount;
  214. if(frames>BUFFER_COUNT){
  215. frames = BUFFER_COUNT;
  216. }
  217. if(file->settings.mChannels==1){
  218. rendered = (int)openmpt_module_read_mono(file->mod,file->settings.mFrequency,frames,&file->buf[frames*0]);
  219. }else if(file->settings.mChannels==2){
  220. rendered = (int)openmpt_module_read_stereo(file->mod,file->settings.mFrequency,frames,&file->buf[frames*0],&file->buf[frames*1]);
  221. }else if(file->settings.mChannels==4){
  222. rendered = (int)openmpt_module_read_quad(file->mod,file->settings.mFrequency,frames,&file->buf[frames*0],&file->buf[frames*1],&file->buf[frames*2],&file->buf[frames*3]);
  223. }else{
  224. return 0;
  225. }
  226. in = file->buf;
  227. if(file->mixerproc&&file->mixerbuf){
  228. mixbuf=file->mixerbuf;
  229. for(frame=0;frame<frames;frame++){
  230. for(channel=0;channel<file->settings.mChannels;channel++){
  231. *mixbuf = in[frames*channel+frame]<<(32-16-1-MIXING_ATTENUATION);
  232. mixbuf++;
  233. }
  234. }
  235. file->mixerproc(file->mixerbuf,file->settings.mChannels*frames,file->settings.mChannels);
  236. mixbuf=file->mixerbuf;
  237. for(frame=0;frame<frames;frame++){
  238. for(channel=0;channel<file->settings.mChannels;channel++){
  239. in[frames*channel+frame] = *mixbuf>>(32-16-1-MIXING_ATTENUATION);
  240. mixbuf++;
  241. }
  242. }
  243. }
  244. if(file->settings.mBits==8){
  245. for(frame=0;frame<frames;frame++){
  246. for(channel=0;channel<file->settings.mChannels;channel++){
  247. *buf8 = in[frames*channel+frame]/256+0x80;
  248. buf8++;
  249. }
  250. }
  251. }else if(file->settings.mBits==16){
  252. for(frame=0;frame<frames;frame++){
  253. for(channel=0;channel<file->settings.mChannels;channel++){
  254. *buf16 = in[frames*channel+frame];
  255. buf16++;
  256. }
  257. }
  258. }else if(file->settings.mBits==32){
  259. for(frame=0;frame<frames;frame++){
  260. for(channel=0;channel<file->settings.mChannels;channel++){
  261. *buf32 = in[frames*channel+frame] << (32-16-1-MIXING_ATTENUATION);
  262. buf32++;
  263. }
  264. }
  265. }else{
  266. return 0;
  267. }
  268. totalrendered += rendered;
  269. framecount -= frames;
  270. if(!rendered) break;
  271. }
  272. memset(((char*)buffer)+totalrendered*framesize,0,size-totalrendered*framesize);
  273. return totalrendered*framesize;
  274. }
  275. LIBOPENMPT_MODPLUG_API const char* ModPlug_GetName(ModPlugFile* file)
  276. {
  277. if(!file) return NULL;
  278. return file->name;
  279. }
  280. LIBOPENMPT_MODPLUG_API int ModPlug_GetLength(ModPlugFile* file)
  281. {
  282. if(!file) return 0;
  283. return (int)(openmpt_module_get_duration_seconds(file->mod)*1000.0);
  284. }
  285. LIBOPENMPT_MODPLUG_API void ModPlug_Seek(ModPlugFile* file, int millisecond)
  286. {
  287. if(!file) return;
  288. openmpt_module_set_position_seconds(file->mod,(double)millisecond*0.001);
  289. }
  290. LIBOPENMPT_MODPLUG_API void ModPlug_GetSettings(ModPlug_Settings* settings)
  291. {
  292. if(!settings) return;
  293. memcpy(settings,&globalsettings,sizeof(ModPlug_Settings));
  294. }
  295. LIBOPENMPT_MODPLUG_API void ModPlug_SetSettings(const ModPlug_Settings* settings)
  296. {
  297. if(!settings) return;
  298. memcpy(&globalsettings,settings,sizeof(ModPlug_Settings));
  299. }
  300. LIBOPENMPT_MODPLUG_API unsigned int ModPlug_GetMasterVolume(ModPlugFile* file)
  301. {
  302. int32_t val;
  303. if(!file) return 0;
  304. val = 0;
  305. if(!openmpt_module_get_render_param(file->mod,OPENMPT_MODULE_RENDER_MASTERGAIN_MILLIBEL,&val)) return 128;
  306. return (unsigned int)(128.0*pow(10.0,val*0.0005));
  307. }
  308. LIBOPENMPT_MODPLUG_API void ModPlug_SetMasterVolume(ModPlugFile* file,unsigned int cvol)
  309. {
  310. if(!file) return;
  311. openmpt_module_set_render_param(file->mod,OPENMPT_MODULE_RENDER_MASTERGAIN_MILLIBEL,(int32_t)(2000.0*log10(cvol/128.0)));
  312. }
  313. LIBOPENMPT_MODPLUG_API int ModPlug_GetCurrentSpeed(ModPlugFile* file)
  314. {
  315. if(!file) return 0;
  316. return openmpt_module_get_current_speed(file->mod);
  317. }
  318. LIBOPENMPT_MODPLUG_API int ModPlug_GetCurrentTempo(ModPlugFile* file)
  319. {
  320. if(!file) return 0;
  321. return openmpt_module_get_current_tempo(file->mod);
  322. }
  323. LIBOPENMPT_MODPLUG_API int ModPlug_GetCurrentOrder(ModPlugFile* file)
  324. {
  325. if(!file) return 0;
  326. return openmpt_module_get_current_order(file->mod);
  327. }
  328. LIBOPENMPT_MODPLUG_API int ModPlug_GetCurrentPattern(ModPlugFile* file)
  329. {
  330. if(!file) return 0;
  331. return openmpt_module_get_current_pattern(file->mod);
  332. }
  333. LIBOPENMPT_MODPLUG_API int ModPlug_GetCurrentRow(ModPlugFile* file)
  334. {
  335. if(!file) return 0;
  336. return openmpt_module_get_current_row(file->mod);
  337. }
  338. LIBOPENMPT_MODPLUG_API int ModPlug_GetPlayingChannels(ModPlugFile* file)
  339. {
  340. if(!file) return 0;
  341. return openmpt_module_get_current_playing_channels(file->mod);
  342. }
  343. LIBOPENMPT_MODPLUG_API void ModPlug_SeekOrder(ModPlugFile* file,int order)
  344. {
  345. if(!file) return;
  346. openmpt_module_set_position_order_row(file->mod,order,0);
  347. }
  348. LIBOPENMPT_MODPLUG_API int ModPlug_GetModuleType(ModPlugFile* file)
  349. {
  350. const char* type;
  351. int retval;
  352. if(!file) return 0;
  353. type = openmpt_module_get_metadata(file->mod,"type");
  354. retval = MOD_TYPE_NONE;
  355. if(!type){
  356. return retval;
  357. }
  358. if(!strcmp(type,"mod")){
  359. retval = MOD_TYPE_MOD;
  360. }else if(!strcmp(type,"s3m")){
  361. retval = MOD_TYPE_S3M;
  362. }else if(!strcmp(type,"xm")){
  363. retval = MOD_TYPE_XM;
  364. }else if(!strcmp(type,"med")){
  365. retval = MOD_TYPE_MED;
  366. }else if(!strcmp(type,"mtm")){
  367. retval = MOD_TYPE_MTM;
  368. }else if(!strcmp(type,"it")){
  369. retval = MOD_TYPE_IT;
  370. }else if(!strcmp(type,"669")){
  371. retval = MOD_TYPE_669;
  372. }else if(!strcmp(type,"ult")){
  373. retval = MOD_TYPE_ULT;
  374. }else if(!strcmp(type,"stm")){
  375. retval = MOD_TYPE_STM;
  376. }else if(!strcmp(type,"far")){
  377. retval = MOD_TYPE_FAR;
  378. }else if(!strcmp(type,"s3m")){
  379. retval = MOD_TYPE_WAV;
  380. }else if(!strcmp(type,"amf")){
  381. retval = MOD_TYPE_AMF;
  382. }else if(!strcmp(type,"ams")){
  383. retval = MOD_TYPE_AMS;
  384. }else if(!strcmp(type,"dsm")){
  385. retval = MOD_TYPE_DSM;
  386. }else if(!strcmp(type,"mdl")){
  387. retval = MOD_TYPE_MDL;
  388. }else if(!strcmp(type,"okt")){
  389. retval = MOD_TYPE_OKT;
  390. }else if(!strcmp(type,"mid")){
  391. retval = MOD_TYPE_MID;
  392. }else if(!strcmp(type,"dmf")){
  393. retval = MOD_TYPE_DMF;
  394. }else if(!strcmp(type,"ptm")){
  395. retval = MOD_TYPE_PTM;
  396. }else if(!strcmp(type,"dbm")){
  397. retval = MOD_TYPE_DBM;
  398. }else if(!strcmp(type,"mt2")){
  399. retval = MOD_TYPE_MT2;
  400. }else if(!strcmp(type,"amf0")){
  401. retval = MOD_TYPE_AMF0;
  402. }else if(!strcmp(type,"psm")){
  403. retval = MOD_TYPE_PSM;
  404. }else if(!strcmp(type,"j2b")){
  405. retval = MOD_TYPE_J2B;
  406. }else if(!strcmp(type,"abc")){
  407. retval = MOD_TYPE_ABC;
  408. }else if(!strcmp(type,"pat")){
  409. retval = MOD_TYPE_PAT;
  410. }else if(!strcmp(type,"umx")){
  411. retval = MOD_TYPE_UMX;
  412. }else{
  413. retval = MOD_TYPE_IT; /* fallback, most complex type */
  414. }
  415. openmpt_free_string(type);
  416. return retval;
  417. }
  418. LIBOPENMPT_MODPLUG_API char* ModPlug_GetMessage(ModPlugFile* file)
  419. {
  420. if(!file) return NULL;
  421. return file->message;
  422. }
  423. LIBOPENMPT_MODPLUG_API unsigned int ModPlug_NumInstruments(ModPlugFile* file)
  424. {
  425. if(!file) return 0;
  426. return openmpt_module_get_num_instruments(file->mod);
  427. }
  428. LIBOPENMPT_MODPLUG_API unsigned int ModPlug_NumSamples(ModPlugFile* file)
  429. {
  430. if(!file) return 0;
  431. return openmpt_module_get_num_samples(file->mod);
  432. }
  433. LIBOPENMPT_MODPLUG_API unsigned int ModPlug_NumPatterns(ModPlugFile* file)
  434. {
  435. if(!file) return 0;
  436. return openmpt_module_get_num_patterns(file->mod);
  437. }
  438. LIBOPENMPT_MODPLUG_API unsigned int ModPlug_NumChannels(ModPlugFile* file)
  439. {
  440. if(!file) return 0;
  441. return openmpt_module_get_num_channels(file->mod);
  442. }
  443. LIBOPENMPT_MODPLUG_API unsigned int ModPlug_SampleName(ModPlugFile* file, unsigned int qual, char* buff)
  444. {
  445. const char* str;
  446. char buf[32];
  447. if(!file) return 0;
  448. str = openmpt_module_get_sample_name(file->mod,qual-1);
  449. memset(buf,0,32);
  450. if(str){
  451. strncpy(buf,str,31);
  452. openmpt_free_string(str);
  453. }
  454. if(buff){
  455. strncpy(buff,buf,32);
  456. }
  457. return (unsigned int)strlen(buf);
  458. }
  459. LIBOPENMPT_MODPLUG_API unsigned int ModPlug_InstrumentName(ModPlugFile* file, unsigned int qual, char* buff)
  460. {
  461. const char* str;
  462. char buf[32];
  463. if(!file) return 0;
  464. str = openmpt_module_get_instrument_name(file->mod,qual-1);
  465. memset(buf,0,32);
  466. if(str){
  467. strncpy(buf,str,31);
  468. openmpt_free_string(str);
  469. }
  470. if(buff){
  471. strncpy(buff,buf,32);
  472. }
  473. return (unsigned int)strlen(buf);
  474. }
  475. LIBOPENMPT_MODPLUG_API ModPlugNote* ModPlug_GetPattern(ModPlugFile* file, int pattern, unsigned int* numrows)
  476. {
  477. int c;
  478. int r;
  479. int numr;
  480. int numc;
  481. ModPlugNote note;
  482. if(!file) return NULL;
  483. if(numrows){
  484. *numrows = openmpt_module_get_pattern_num_rows(file->mod,pattern);
  485. }
  486. if(pattern<0||pattern>=openmpt_module_get_num_patterns(file->mod)){
  487. return NULL;
  488. }
  489. if(!file->patterns){
  490. file->patterns = malloc(sizeof(ModPlugNote*)*openmpt_module_get_pattern_num_rows(file->mod,pattern));
  491. if(!file->patterns) return NULL;
  492. memset(file->patterns,0,sizeof(ModPlugNote*)*openmpt_module_get_pattern_num_rows(file->mod,pattern));
  493. }
  494. if(!file->patterns[pattern]){
  495. file->patterns[pattern] = malloc(sizeof(ModPlugNote)*openmpt_module_get_pattern_num_rows(file->mod,pattern)*openmpt_module_get_num_channels(file->mod));
  496. if(!file->patterns[pattern]) return NULL;
  497. memset(file->patterns[pattern],0,sizeof(ModPlugNote)*openmpt_module_get_pattern_num_rows(file->mod,pattern)*openmpt_module_get_num_channels(file->mod));
  498. }
  499. numr = openmpt_module_get_pattern_num_rows(file->mod,pattern);
  500. numc = openmpt_module_get_num_channels(file->mod);
  501. for(r=0;r<numr;r++){
  502. for(c=0;c<numc;c++){
  503. memset(&note,0,sizeof(ModPlugNote));
  504. note.Note = openmpt_module_get_pattern_row_channel_command(file->mod,pattern,r,c,OPENMPT_MODULE_COMMAND_NOTE);
  505. note.Instrument = openmpt_module_get_pattern_row_channel_command(file->mod,pattern,r,c,OPENMPT_MODULE_COMMAND_INSTRUMENT);
  506. note.VolumeEffect = openmpt_module_get_pattern_row_channel_command(file->mod,pattern,r,c,OPENMPT_MODULE_COMMAND_VOLUMEEFFECT);
  507. note.Effect = openmpt_module_get_pattern_row_channel_command(file->mod,pattern,r,c,OPENMPT_MODULE_COMMAND_EFFECT);
  508. note.Volume = openmpt_module_get_pattern_row_channel_command(file->mod,pattern,r,c,OPENMPT_MODULE_COMMAND_VOLUME);
  509. note.Parameter = openmpt_module_get_pattern_row_channel_command(file->mod,pattern,r,c,OPENMPT_MODULE_COMMAND_PARAMETER);
  510. memcpy(&file->patterns[pattern][r*numc+c],&note,sizeof(ModPlugNote));
  511. }
  512. }
  513. return file->patterns[pattern];
  514. }
  515. LIBOPENMPT_MODPLUG_API void ModPlug_InitMixerCallback(ModPlugFile* file,ModPlugMixerProc proc)
  516. {
  517. if(!file) return;
  518. if(!file->mixerbuf){
  519. file->mixerbuf = malloc(BUFFER_COUNT*sizeof(signed int)*4);
  520. }
  521. file->mixerproc = proc;
  522. }
  523. LIBOPENMPT_MODPLUG_API void ModPlug_UnloadMixerCallback(ModPlugFile* file)
  524. {
  525. if(!file) return;
  526. file->mixerproc = NULL;
  527. if(file->mixerbuf){
  528. free(file->mixerbuf);
  529. file->mixerbuf = NULL;
  530. }
  531. }
  532. LIBOPENMPT_MODPLUG_API char ModPlug_ExportS3M(ModPlugFile* file, const char* filepath)
  533. {
  534. (void)file;
  535. /* not implemented */
  536. fprintf(stderr,"libopenmpt-modplug: error: ModPlug_ExportS3M(%s) not implemented.\n",filepath);
  537. return 0;
  538. }
  539. LIBOPENMPT_MODPLUG_API char ModPlug_ExportXM(ModPlugFile* file, const char* filepath)
  540. {
  541. (void)file;
  542. /* not implemented */
  543. fprintf(stderr,"libopenmpt-modplug: error: ModPlug_ExportXM(%s) not implemented.\n",filepath);
  544. return 0;
  545. }
  546. LIBOPENMPT_MODPLUG_API char ModPlug_ExportMOD(ModPlugFile* file, const char* filepath)
  547. {
  548. (void)file;
  549. /* not implemented */
  550. fprintf(stderr,"libopenmpt-modplug: error: ModPlug_ExportMOD(%s) not implemented.\n",filepath);
  551. return 0;
  552. }
  553. LIBOPENMPT_MODPLUG_API char ModPlug_ExportIT(ModPlugFile* file, const char* filepath)
  554. {
  555. (void)file;
  556. /* not implemented */
  557. fprintf(stderr,"libopenmpt-modplug: error: ModPlug_ExportIT(%s) not implemented.\n",filepath);
  558. return 0;
  559. }
  560. #endif /* NO_LIBMODPLUG */