📄 sample.c
字号:
sam_load_file_as_sample (AudioFileRef * afref, SFData * sf){ gint16 *buf; gint16 *och; /* other channel ptr, for stereo samples */ gint samples; gint i, i2; SFSample *samptr; /* clean up sample buffer if excessive unused sample waste */ sam_buf_clean (); /* allocate space for sample data (3 times for stereo data to separate) */ if (!(buf = safe_malloc (afref->info.frames * ((afref->info.channels == 2) ? 3 : 1) * 2))) return (NULL); /* read the sample into memory */ if (!sam_read_file (afref, buf, afref->info.frames)) { g_free (buf); return (NULL); } samples = afref->info.frames * afref->info.channels; if (afref->info.width == 16 && !afref->info.signd) { /* u16 > s16 */ for (i = 0; i < samples; i++) buf[i] ^= 0x8000; } else if (afref->info.width == 8 && !afref->info.signd) { /* u8 -> s16 */ for (i = 0; i < samples; i++) buf[i] = (buf[i] << 8) ^ 0x8000; } else if (afref->info.width == 8) { /* signed 8 -> signed 16 */ for (i = 0; i < samples; i++) buf[i] = buf[i] << 8; } /* sample data is now signed 16 bit, check if data needs separation */ if (afref->info.channels == 2) { och = buf + afref->info.frames * 2; /* och points after sample data */ i2 = afref->info.frames; for (i = 0; i < i2; i++) och[i] = buf[(i << 1) + 1]; for (i = 1; i < i2; i++) buf[i] = buf[i << 1]; } samptr = sam_create_sample ("", afref->info.rate, buf, afref->info.frames, sf); if (!samptr) { g_free (buf); return (NULL); } if (afref->info.channels == 2) { if (!sam_create_sample ("", afref->info.rate, och, afref->info.frames, sf)) { g_free (buf); sfont_remove_sample (sf, samptr); /* remove already loaded ch */ return (NULL); } } g_free (buf); return (samptr);}/* check if audio is okay for loading as sample data */gintsam_check_file (AudioFileRef * afref){ if (afref->info.channels != 1 && afref->info.channels != 2) { logit (LogFubar, _("Sample must be mono or stereo")); return (FAIL); }#ifndef AUDIOFILE_ZERO_TWO if (afref->info.width != 16 && afref->info.width != 8) { /* check width */ logit (LogFubar, _("Sample must be 8 or 16 bits, sample is %d bits"), afref->info.width); return (FAIL); }#endif if (afref->info.rate < SF_MIN_SAMPLERATE || afref->info.rate > SF_MAX_SAMPLERATE) { logit (LogFubar, _("Sample rate is out of bounds, sample rate is %d"), afref->info.rate); return (FAIL); } if (afref->info.frames < SF_MIN_SAMPLE_LENGTH) { /* sample is too small? */ logit (LogFubar, _("Sample is less than the minimum of %d samples"), SF_MIN_SAMPLE_LENGTH); return (FAIL); } /* sample is too big? */ if (afref->info.frames * 2 > MAX_SAMPLE_SIZE) { logit (LogFubar, _("Sample is larger than %d bytes"), MAX_SAMPLE_SIZE); return (FAIL); } return (OK);}gintsam_export_sample (SFSample * sam, SFData * sf, gchar * fname, enum AudioFileType filetype){ AudioInfo afnfo; AudioFileRef *afref; void *buf; /* load buffer with sample data */ if (!(buf = sam_load_sample (sam, sam->end + 1, 0, NULL))) return (FAIL); afnfo.filetype = filetype; /* enum in sample.h */ afnfo.rate = sam->samplerate; afnfo.channels = 1; afnfo.width = 16; /* open audio file for writing */ if (!(afref = sam_open_file (fname, FALSE, &afnfo))) { g_free (buf); return (FAIL); } if (!sam_write_file (afref, buf, sam->end + 1)) { sam_close_file (afref); g_free (buf); return (FAIL); } sam_close_file (afref); g_free (buf); return (OK);}/* +++ audio library specific routines +++ */#ifndef WITH_AUDIOFILE /*---- libsndfile routines ----*//* libsndfile: open audio file */AudioFileRef *sam_open_file (gchar * fname, gboolean read, AudioInfo * afmt){ AudioFileRef *afref; SNDFILE *afh; SF_INFO sfnfo; gboolean raw = FALSE; gchar errbuf[100]; if (read && afmt) raw = TRUE; if (raw || !read) { /* raw file load or write mode requested? */ if (!afmt) return (NULL); /* afmt must be specified */ sfnfo.samplerate = afmt->rate; sfnfo.channels = afmt->channels; sfnfo.pcmbitwidth = afmt->width; if (!read) { /* if write mode, then see what format to write in */ switch (afmt->filetype) { case AUDIO_TYPE_AIFF: sfnfo.format = SF_FORMAT_AIFF; break; case AUDIO_TYPE_AU: sfnfo.format = SF_FORMAT_AU; break; default: sfnfo.format = SF_FORMAT_WAV; break; } sfnfo.format |= SF_FORMAT_PCM; } else { /* raw mode read */ sfnfo.format = SF_FORMAT_RAW; if (afmt->width > 8) sfnfo.format |= (afmt->lendian ? SF_FORMAT_PCM_LE : SF_FORMAT_PCM_BE); else sfnfo.format |= (afmt->signd ? SF_FORMAT_PCM_S8 : SF_FORMAT_PCM_U8); } } if (read) { /* read mode requested? */ if (!(afh = sf_open_read (fname, &sfnfo))) { sf_error_str (afh, errbuf, 100); logit (LogFubar, "libsndfile: %s: %s", _("Failed to open audio file for reading"), errbuf); return (NULL); } } else { /* write mode requested? */ if (!(afh = sf_open_write (fname, &sfnfo))) { sf_error_str (afh, errbuf, 100); logit (LogFubar, "libsndfile: %s: %s", _("Failed to open audio file for writing"), errbuf); return (NULL); } } if (!(afref = safe_malloc (sizeof (AudioFileRef)))) { sf_close (afref->afh); return (NULL); } afref->afh = afh; /* set sample information */ afref->info.frames = sfnfo.samples; afref->info.rate = sfnfo.samplerate; afref->info.channels = sfnfo.channels; afref->info.width = sfnfo.pcmbitwidth; afref->info.lendian = TRUE; afref->info.signd = TRUE; return (afref);}gintsam_read_file (AudioFileRef * afref, void *buf, gint count){ gchar errbuf[100]; gint c; if ((c = sf_readf_short (afref->afh, buf, count)) != count) { sf_error_str (afref->afh, errbuf, 100); logit (LogFubar, "libsndfile: %s (%d of %d frames): %s", _("Failed to read sample data"), c, count, errbuf); return (FAIL); } return (OK);}gintsam_write_file (AudioFileRef * afref, void *buf, gint count){ gchar errbuf[100]; gint c; if ((c = sf_writef_short (afref->afh, buf, count)) != count) { sf_error_str (afref->afh, errbuf, 100); logit (LogFubar, "libsndfile: %s (%d of %d frames): %s", _("Failed to write sample data"), c, count, errbuf); return (FAIL); } return (OK);}/* libsndfile: close an open audio file */voidsam_close_file (AudioFileRef * afref){ sf_close (afref->afh); g_free (afref);}#else /*---- AUDIOFILE routines ----*/AudioFileRef *sam_open_file (gchar * fname, gboolean read, AudioInfo * afmt){ AudioFileRef *afref; AFfilehandle affd; AFfilesetup afsetup = NULL; gint fmt, wdth, chan, samrate, frame_count; gboolean raw = FALSE; if (read && afmt) raw = TRUE; if (raw || !read) { gint filefmt; if (!afmt) return (NULL); afsetup = afNewFileSetup (); afInitChannels (afsetup, AF_DEFAULT_TRACK, afmt->channels); afInitRate (afsetup, AF_DEFAULT_TRACK, afmt->rate); afInitSampleFormat (afsetup, AF_DEFAULT_TRACK, afmt->signd ? AF_SAMPFMT_TWOSCOMP : AF_SAMPFMT_UNSIGNED, afmt->width); if (!read) /* write file? */ { switch (afmt->filetype) { case AUDIO_TYPE_AIFF: filefmt = AF_FILE_AIFFC; break; case AUDIO_TYPE_AU: filefmt = AF_FILE_NEXTSND; break; default: filefmt = AF_FILE_WAVE; break; } } else { filefmt = AF_FILE_RAWDATA; afInitByteOrder (afsetup, AF_DEFAULT_TRACK, afmt->lendian ? AF_BYTEORDER_LITTLEENDIAN : AF_BYTEORDER_BIGENDIAN); } afInitFileFormat (afsetup, filefmt); } /* open the audio file */ affd = afOpenFile (fname, read ? "r" : "w", afsetup); if (!affd) { logit (LogFubar, "audiofile: %s", read ? _("Failed to open audio file for reading") : _("Failed to open audio file for writing")); return (NULL); }#ifdef AUDIOFILE_ZERO_TWO /* set up the virtual sample format (audiofile will convert to this) */ fmt = AF_SAMPFMT_TWOSCOMP; wdth = 16; afSetVirtualSampleFormat (affd, AF_DEFAULT_TRACK, fmt, wdth); /* 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);#else afGetSampleFormat (affd, AF_DEFAULT_TRACK, &fmt, &wdth);#endif chan = afGetChannels (affd, AF_DEFAULT_TRACK); samrate = afGetRate (affd, AF_DEFAULT_TRACK); frame_count = afGetFrameCount (affd, AF_DEFAULT_TRACK); if (!(afref = safe_malloc (sizeof (AudioFileRef)))) { afCloseFile (affd); return (NULL); } /* assign loaded file format vars, so calling function can view them */ afref->info.frames = frame_count; afref->info.rate = samrate; afref->info.channels = chan; afref->info.width = wdth; afref->info.lendian = TRUE; /* audiofile reports incorrectly for 8bit UNSIGNED/SIGNED format? */ if (wdth != 8) afref->info.signd = (fmt == AF_SAMPFMT_TWOSCOMP); else afref->info.signd = FALSE; afref->afh = affd; return (afref);}gintsam_read_file (AudioFileRef * afref, void *buf, gint count){ gint c, i; if ((c = afReadFrames (afref->afh, AF_DEFAULT_TRACK, buf, count)) != count) { logit (LogFubar, "libaudiofile: %s (%d of %d frames)", _("Failed to read sample data"), c, count); return (FAIL); } /* if 8 bit sample data, store in 16 bits (not converted) like libsndfile */ if (afref->info.width == 8) { for (i = c - 1; i >= 0; i--) ((gint16 *) buf)[i] = ((gint8 *) buf)[i]; } return (OK);}gintsam_write_file (AudioFileRef * afref, void *buf, gint count){ gint c; if ((c = afWriteFrames (afref->afh, AF_DEFAULT_TRACK, buf, count)) != count) { logit (LogFubar, "libaudiofile: %s (%d of %d frames)", _("Failed to write sample data"), c, count); return (FAIL); } return (OK);}/* AUDIOFILE: close an open audio file */voidsam_close_file (AudioFileRef * afref){ afCloseFile (afref->afh); g_free (afref);}#endif /* audiofile routines */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -