00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00031 #include "stdinc.h"
00032
00033 #include <sys/mman.h>
00034 #include <modplug.h>
00035
00036 #include "audio_file.h"
00037 #include "audio_format.h"
00038 #include "audio_output.h"
00039
00043 #define SAMPLERATE 44100
00044
00047 #define BYTESPERSAMPLE 4
00048
00052 struct modplug_drv_data {
00056 void *map_base;
00060 size_t map_len;
00064 ModPlugFile *modplug;
00068 off_t sample;
00069 };
00070
00074 static void
00075 modplug_init(void)
00076 {
00077 ModPlug_Settings mset;
00078
00079 ModPlug_GetSettings(&mset);
00080 mset.mChannels = 2;
00081 mset.mBits = 16;
00082 mset.mFrequency = SAMPLERATE;
00083 ModPlug_SetSettings(&mset);
00084 }
00085
00086 int
00087 modplug_open(struct audio_file *fd, const char *ext)
00088 {
00089 struct modplug_drv_data *data;
00090 const char *title;
00091
00092
00093 if (ext == NULL)
00094 return (-1);
00095 if (g_ascii_strcasecmp(ext, "mod") != 0 &&
00096 g_ascii_strcasecmp(ext, "s3m") != 0 &&
00097 g_ascii_strcasecmp(ext, "it") != 0 &&
00098 g_ascii_strcasecmp(ext, "xm") != 0)
00099 return (-1);
00100
00101
00102 if (fd->stream)
00103 return (-1);
00104
00105 data = g_slice_new(struct modplug_drv_data);
00106
00107
00108 fseek(fd->fp, 0, SEEK_END);
00109 data->map_len = ftello(fd->fp);
00110
00111
00112 data->map_base = mmap(NULL, data->map_len, PROT_READ,
00113 MAP_PRIVATE, fileno(fd->fp), 0);
00114 if (data->map_base == MAP_FAILED)
00115 goto free;
00116
00117
00118 modplug_init();
00119 data->modplug = ModPlug_Load(data->map_base, data->map_len);
00120 if (data->modplug != NULL) {
00121 data->sample = 0;
00122 fd->drv_data = data;
00123 fd->srate = SAMPLERATE;
00124 fd->channels = 2;
00125
00126 fd->time_len = ModPlug_GetLength(data->modplug) / 1000;
00127 title = ModPlug_GetName(data->modplug);
00128 if (title != NULL && title[0] != '\0')
00129 fd->title = g_strdup(title);
00130 return (0);
00131 }
00132
00133 munmap(data->map_base, data->map_len);
00134 free: g_slice_free(struct modplug_drv_data, data);
00135 return (1);
00136 }
00137
00138 void
00139 modplug_close(struct audio_file *fd)
00140 {
00141 struct modplug_drv_data *data = fd->drv_data;
00142
00143 ModPlug_Unload(data->modplug);
00144 munmap(data->map_base, data->map_len);
00145 g_slice_free(struct modplug_drv_data, data);
00146 }
00147
00148 size_t
00149 modplug_read(struct audio_file *fd, int16_t *buf, size_t len)
00150 {
00151 struct modplug_drv_data *data = fd->drv_data;
00152 int rlen;
00153
00154 rlen = ModPlug_Read(data->modplug, buf, len * sizeof(int16_t));
00155 data->sample += rlen / BYTESPERSAMPLE;
00156 fd->time_cur = data->sample / SAMPLERATE;
00157
00158 return (rlen / sizeof(int16_t));
00159 }
00160
00161 void
00162 modplug_seek(struct audio_file *fd, int len, int rel)
00163 {
00164 struct modplug_drv_data *data = fd->drv_data;
00165 size_t off;
00166
00167 off = len * SAMPLERATE;
00168 if (rel)
00169 off += data->sample;
00170
00171 off = CLAMP(off, 0, (fd->time_len - 1) * SAMPLERATE);
00172
00173 ModPlug_Seek(data->modplug, (off * 10) / (SAMPLERATE / 100));
00174 data->sample = off;
00175 fd->time_cur = data->sample / SAMPLERATE;
00176 }