/* * samplelib_audiofile.c - SwamiSamplelib plugin for libaudiofile * * Swami * Copyright (C) 1999-2003 Josh Green * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA or point your web browser to http://www.gnu.org. * * To contact the author of this program: * Email: Josh Green * Swami homepage: http://swami.sourceforge.net */ #include "config.h" #include #include #include #include #include #include #include #include #include "samplelib_audiofile.h" #include "i18n.h" static int plugin_audiofile_init (GModule *module, SwamiPlugin *plugin); static GType samplelib_audiofile_get_type (void); static void samplelib_audiofile_class_init (SamplelibAudiofileClass *klass); static void samplelib_audiofile_init (SamplelibAudiofile *samplelib); static int samplelib_audiofile_open (SwamiSamplelibHandle *handle); static void samplelib_audiofile_close (SwamiSamplelibHandle *handle); static int samplelib_audiofile_read (SwamiSamplelibHandle *handle, int frames, gint16 *buf); static int samplelib_audiofile_write (SwamiSamplelibHandle *handle, int frames, const gint16 *buf); /* set plugin information */ SWAMI_PLUGIN_DESC (SWAMI_VERSION_MAJOR, SWAMI_VERSION_MINOR, "audiofile", N_("audiofile - audiofile library plugin"), N_("Josh Green"), "", plugin_audiofile_init); static int plugin_audiofile_init (GModule *module, SwamiPlugin *plugin) { /* initialize SamplelibAudiofile type */ samplelib_audiofile_get_type (); return (SWAMI_OK); } static GType samplelib_audiofile_get_type (void) { static GType item_type = 0; if (!item_type) { static const GTypeInfo item_info = { sizeof (SamplelibAudiofileClass), NULL, NULL, (GClassInitFunc) samplelib_audiofile_class_init, NULL, NULL, sizeof (SamplelibAudiofile), 0, (GInstanceInitFunc) samplelib_audiofile_init, }; item_type = g_type_register_static (SWAMI_TYPE_SAMPLELIB, "SamplelibAudiofile", &item_info, G_TYPE_FLAG_ABSTRACT); } return (item_type); } static void samplelib_audiofile_class_init (SamplelibAudiofileClass *klass) { SwamiSamplelibClass *samplelib_class; samplelib_class = SWAMI_SAMPLELIB_CLASS (klass); samplelib_class->open = samplelib_audiofile_open; samplelib_class->close = samplelib_audiofile_close; samplelib_class->read = samplelib_audiofile_read; samplelib_class->write = samplelib_audiofile_write; } static void samplelib_audiofile_init (SamplelibAudiofile *samplelib) { } static int samplelib_audiofile_open (SwamiSamplelibHandle *handle) { SwamiSamplelibParams *params = &handle->params; AFfilehandle affd; AFfilesetup afsetup = NULL; char smode[2]; /* convert character mode to string */ gboolean writeloop = FALSE, writeinst = FALSE; if (params->file_type == SWAMI_SAMPLELIB_TYPE_RAW || handle->mode == 'w') { int filefmt; afsetup = afNewFileSetup (); afInitChannels (afsetup, AF_DEFAULT_TRACK, params->channels); afInitRate (afsetup, AF_DEFAULT_TRACK, params->rate); afInitSampleFormat (afsetup, AF_DEFAULT_TRACK, params->signd ? AF_SAMPFMT_TWOSCOMP : AF_SAMPFMT_UNSIGNED, params->width); if (handle->mode == 'w') /* write file? */ { switch (params->file_type) { case SWAMI_SAMPLELIB_TYPE_WAVE: filefmt = AF_FILE_WAVE; break; case SWAMI_SAMPLELIB_TYPE_AU: filefmt = AF_FILE_NEXTSND; break; default: filefmt = AF_FILE_AIFF; break; } afInitFileFormat (afsetup, filefmt); // Yeah maybe someday if loop/inst support is added for other types // if (afQueryLong (AF_QUERYTYPE_INSTPARAM, AF_QUERY_SUPPORTED, // filefmt, 0, 0)) if (filefmt == AF_FILE_AIFF) { writeinst = TRUE; // && afQueryLong (AF_QUERYTYPE_LOOP, AF_QUERY_SUPPORTED, // filefmt, 0, 0)) /* set loop info if supported by file type */ if (params->loop_type != SWAMI_AUDIO_LOOP_NONE) { int markerIDs[4] = { 1, 2, 3, 4 }; int loopIDs[2] = { 1, 2 }; afInitMarkIDs (afsetup, AF_DEFAULT_TRACK, markerIDs, 4); afInitLoopIDs (afsetup, AF_DEFAULT_INST, loopIDs, 2); writeloop = TRUE; } } } else /** RAW file read mode */ { filefmt = AF_FILE_RAWDATA; afInitFileFormat (afsetup, filefmt); afInitByteOrder (afsetup, AF_DEFAULT_TRACK, params->lendian ? AF_BYTEORDER_LITTLEENDIAN : AF_BYTEORDER_BIGENDIAN); } } smode[0] = handle->mode; smode[1] = '\0'; /* open the audio file */ affd = afOpenFile (handle->filename, smode, afsetup); if (afsetup) afFreeFileSetup (afsetup); /* free setup structure */ if (!affd) { if (handle->mode == 'w') g_critical (_("Failed to open audio file \"%s\" for writing"), handle->filename); else g_critical (_("Failed to open audio file \"%s\" for reading"), handle->filename); return (SWAMI_FAIL); } if (handle->mode == 'r') { int loopcount, instcount; loopcount = afGetLoopIDs (affd, AF_DEFAULT_INST, NULL); if (loopcount > 0) /* any loops? (we only use 1) */ { int loopids[loopcount]; int markID; int mode; afGetLoopIDs (affd, AF_DEFAULT_INST, loopids); mode = afGetLoopMode (affd, AF_DEFAULT_INST, loopids[0]); if (mode != AF_LOOP_MODE_NOLOOP) /* loop active? */ { params->loop_type = SWAMI_AUDIO_LOOP_NORMAL; markID = afGetLoopStart (affd, AF_DEFAULT_INST, loopids[0]); params->loop_start = afGetMarkPosition (affd, AF_DEFAULT_TRACK, markID); markID = afGetLoopEnd (affd, AF_DEFAULT_INST, loopids[0]); params->loop_end = afGetMarkPosition (affd, AF_DEFAULT_TRACK, markID); } } instcount = afGetInstIDs (affd, NULL); if (instcount > 0) { int instids[instcount]; afGetInstIDs (affd, instids); params->root_note = afGetInstParamLong (affd, instids[0], AF_INST_MIDI_BASENOTE); params->fine_tune = afGetInstParamLong (affd, instids[0], AF_INST_NUMCENTS_DETUNE); if (params->root_note < 0 || params->root_note > 127) params->root_note = 60; if (params->fine_tune < -99 || params->fine_tune > 99) params->fine_tune = 0; } } else /* write mode */ { if (writeloop) { afSetMarkPosition(affd, AF_DEFAULT_TRACK, 1, params->loop_start); afSetMarkPosition(affd, AF_DEFAULT_TRACK, 2, params->loop_end); afSetLoopStart(affd, AF_DEFAULT_INST, 1, 1); afSetLoopEnd(affd, AF_DEFAULT_INST, 1, 2); afSetLoopMode (affd, AF_DEFAULT_INST, 1, AF_LOOP_MODE_FORW); } if (writeinst) { afSetInstParamLong (affd, AF_DEFAULT_INST, AF_INST_MIDI_BASENOTE, params->root_note); afSetInstParamLong (affd, AF_DEFAULT_INST, AF_INST_NUMCENTS_DETUNE, params->fine_tune); } } /* set up the virtual sample format (audiofile will convert to this) */ afSetVirtualSampleFormat (affd, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16); /* convert to host byte order */ if (G_BYTE_ORDER == G_LITTLE_ENDIAN) afSetVirtualByteOrder (affd, AF_DEFAULT_TRACK, AF_BYTEORDER_LITTLEENDIAN); else afSetVirtualByteOrder (affd, AF_DEFAULT_TRACK, AF_BYTEORDER_BIGENDIAN); params->channels = afGetChannels (affd, AF_DEFAULT_TRACK); params->rate = afGetRate (affd, AF_DEFAULT_TRACK); handle->size = afGetFrameCount (affd, AF_DEFAULT_TRACK); handle->driver_data = affd; return (SWAMI_OK); } /* file close function */ static void samplelib_audiofile_close (SwamiSamplelibHandle *handle) { afCloseFile ((AFfilehandle)(handle->driver_data)); } /* file read function */ static int samplelib_audiofile_read (SwamiSamplelibHandle *handle, int frames, gint16 *buf) { return (afReadFrames ((AFfilehandle)(handle->driver_data), AF_DEFAULT_TRACK, (void *)buf, frames)); } static int samplelib_audiofile_write (SwamiSamplelibHandle *handle, int frames, const gint16 *buf) { return (afWriteFrames ((AFfilehandle)(handle->driver_data), AF_DEFAULT_TRACK, (void *)buf, frames)); }