static void error_number_test (void) { const char *noerror, *errstr ; int k ; print_test_name ("error_number_test", "") ; noerror = sf_error_number (0) ; for (k = 1 ; k < 300 ; k++) { errstr = sf_error_number (k) ; /* Test for termination condition. */ if (errstr == noerror) break ; /* Test for error. */ if (strstr (errstr, "This is a bug in libsndfile.")) { printf ("\n\nError : error number %d : %s\n\n\n", k, errstr) ; exit (1) ; } ; } ; puts ("ok") ; return ; } /* error_number_test */
bool EngineRecord::openFile() { // Unfortunately, we cannot use QFile for writing WAV and AIFF audio. if (m_encoding == ENCODING_WAVE || m_encoding == ENCODING_AIFF){ unsigned long samplerate = m_pSamplerate->get(); // set sfInfo m_sfInfo.samplerate = samplerate; m_sfInfo.channels = 2; if (m_encoding == ENCODING_WAVE) m_sfInfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; else m_sfInfo.format = SF_FORMAT_AIFF | SF_FORMAT_PCM_16; // Creates a new WAVE or AIFF file and writes header information. m_pSndfile = sf_open(m_fileName.toLocal8Bit(), SFM_WRITE, &m_sfInfo); if (m_pSndfile) { sf_command(m_pSndfile, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ; // Set meta data int ret; ret = sf_set_string(m_pSndfile, SF_STR_TITLE, m_baTitle.data()); if(ret != 0) qDebug("libsndfile: %s", sf_error_number(ret)); ret = sf_set_string(m_pSndfile, SF_STR_ARTIST, m_baAuthor.data()); if(ret != 0) qDebug("libsndfile: %s", sf_error_number(ret)); ret = sf_set_string(m_pSndfile, SF_STR_COMMENT, m_baAlbum.data()); if(ret != 0) qDebug("libsndfile: %s", sf_error_number(ret)); } } else { // We can use a QFile to write compressed audio. if (m_pEncoder) { m_file.setFileName(m_fileName); m_file.open(QIODevice::WriteOnly); if (m_file.handle() != -1) { m_dataStream.setDevice(&m_file); } } else { return false; } } // Check if file is really open. if (!fileOpen()) { ErrorDialogProperties* props = ErrorDialogHandler::instance()->newDialogProperties(); props->setType(DLG_WARNING); props->setTitle(tr("Recording")); props->setText("<html>"+tr("Could not create audio file for recording!") +"<p><br>"+tr("Maybe you do not have enough free disk space or file permissions.")+"</p></html>"); ErrorDialogHandler::instance()->requestErrorDialog(props); return false; } return true; }
void xsf_handle_error(SNDFILE *sndfile) { int errnum = sf_error(sndfile); const char *errstr = sf_error_number(errnum); fprintf(stderr, "libsndfile failed: %s\n", errstr); exit(EXIT_FAILURE); }
static void perr(char *text) { int err = sf_error(sndfile); puts("##########################################################"); puts(text); puts(sf_error_number(err)); }
// starts recording to a file as defined by the class parameters int PortAudioSound::StartRecord() { if (!recordflag){ startRecording = TRUE; recordedBlocks = 0L; stopTime = -1.0; sfinfo.channels = 1; sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; sfinfo.frames = framesPerBuffer; sfinfo.samplerate = iSampleRate; timeStr = ""; outfile = sf_open("c:/bat recordings/testfile.wav", SFM_WRITE, &sfinfo); if (outfile == NULL){ int err = sf_error(NULL); const char *errstr = sf_error_number(err); logFile.WriteString((LPCWSTR) errstr); } logFile.WriteString(L"Recording started\n"); startTime = (double) Pa_GetStreamTime(pStream); recordflag = true; } return(0); }
int OlaRandom::ReadSoundFile( char filename[] ) { // open file if( sfread ) { sf_close( sfread ); } sfread = sf_open( filename, SFM_READ, &readinfo ); if( !sfread ) { BB_log( BB_LOG_SEVERE, "[TreesynthIO]: Could not open input file '%s', %s", filename, sf_error_number( sf_error( sfread ) ) ); return 0; } strcpy( ifilename, filename ); // determine number of buffers needed origsize = readinfo.frames; std::cerr << "frames: " << origsize << std::endl; SAFE_DELETE_ARRAY(origbuffer); origbuffer = new float[origsize]; // read sf_seek( sfread, 0, SEEK_SET ); int itemsread = sf_read_float( sfread, origbuffer, origsize); sf_close( sfread ); sfread = NULL; return itemsread; }
int checkErr(int err,int systemScope,const char* message) { switch(systemScope) { case kAudioSystem: if(err != paNoError) printf("Audio system: %s [%s]\n", Pa_GetErrorText(err),message); break; case kMIDISystem: if(err != pmNoError) printf("MIDI system: %s [%s]\n", Pm_GetErrorText(err),message); break; case kSndFileSystem: if(err != 0) printf("Sound File system: %s [%s]\n", sf_error_number(err),message); break; default: printf("Error: %d\n",err); break; } return err; }
static void zero_length_test (const char *filename) { SNDFILE *sndfile ; SF_INFO sfinfo ; FILE *file ; print_test_name (__func__, filename) ; /* Create a zero length file. */ file = fopen (filename, "w") ; exit_if_true (file == NULL, "\n\nLine %d : fopen ('%s') failed.\n", __LINE__, filename) ; fclose (file) ; memset (&sfinfo, 0, sizeof (sfinfo)) ; sndfile = sf_open (filename, SFM_READ, &sfinfo) ; exit_if_true (sndfile != NULL, "\n\nLine %d : should not have received a valid SNDFILE* pointer.\n", __LINE__) ; exit_if_true (0 && sf_error (NULL) != SF_ERR_UNRECOGNISED_FORMAT, "\n\nLine %3d : Error : %s\n should be : %s\n", __LINE__, sf_strerror (NULL), sf_error_number (SF_ERR_UNRECOGNISED_FORMAT)) ; unlink (filename) ; puts ("ok") ; } /* zero_length_test */
static void large_free_test (const char *filename, int format, size_t chunk_size) { SNDFILE * file ; SF_INFO sfinfo ; SF_CHUNK_INFO chunk_info ; char chunk_data [20002] ; short audio [16] ; int err ; print_test_name (__func__, filename) ; exit_if_true (sizeof (chunk_data) <= chunk_size, "\n\nLine %d : sizeof (data) < chunk_size\n\n", __LINE__) ; memset (chunk_data, 53, sizeof (chunk_data)) ; chunk_data [chunk_size] = 0 ; sfinfo.samplerate = 44100 ; sfinfo.channels = 1 ; sfinfo.frames = 0 ; sfinfo.format = format ; file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; /* Set up the chunk to write. */ memset (&chunk_info, 0, sizeof (chunk_info)) ; snprintf (chunk_info.id, sizeof (chunk_info.id), "free") ; chunk_info.id_size = 4 ; chunk_info.data = chunk_data ; chunk_info.datalen = chunk_size ; err = sf_set_chunk (file, &chunk_info) ; exit_if_true ( err != SF_ERR_NO_ERROR, "\n\nLine %d : sf_set_chunk returned for testdata : %s\n\n", __LINE__, sf_error_number (err) ) ; memset (chunk_info.data, 0, chunk_info.datalen) ; /* Add some audio data. */ memset (audio, 0, sizeof (audio)) ; sf_write_short (file, audio, ARRAY_LEN (audio)) ; sf_close (file) ; file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ; exit_if_true ( sfinfo.frames != ARRAY_LEN (audio), "\n\nLine %d : Incorrect sample count (%d should be %d)\n", __LINE__, (int) sfinfo.frames, (int) ARRAY_LEN (audio) ) ; if (chunk_size < 512) check_log_buffer_or_die (file, __LINE__) ; sf_close (file) ; unlink (filename) ; puts ("ok") ; } /* large_free_test */
int close_sndfile(lua_State *L) { soundFileSt *sndf = (soundFileSt *)luaL_checkudata(L, 1, LIBSNDFILE); //std::cout << "closing file " << sndf->filename << std::endl; if(sndf->dac) sndf->dac->playing_files.erase(sndf); int err = sf_close(sndf->sndfile); if(err!=0) luaL_error(L, "error closing file %s : %s",sndf->filename.c_str(),sf_error_number(err)); return 0; }
int destroy_sndfile(lua_State *L) { soundFileSt *sndf = (soundFileSt *)luaL_checkudata(L, 1, LIBSNDFILE); if(sndf->dac) sndf->dac->playing_files.erase(sndf); int err = sf_close(sndf->sndfile); if(err!=0) luaL_error(L, "error closing file %s : %s",sndf->filename.c_str(),sf_error_number(err)); sndf->~soundFileSt(); return 0; }
void EncoderWave::initStream() { // Tell the encoder to automatically convert float input range to the correct output range. sf_command(m_pSndfile, SFC_SET_NORM_FLOAT, NULL, SF_TRUE); // Tell the encoder that, when converting to integer formats, clip // automatically the values that go outside of the allowed range. // Warning! Depending on how libsndfile is compiled autoclip may not work. // Ensure CPU_CLIPS_NEGATIVE and CPU_CLIPS_POSITIVE is setup properly in the build. sf_command(m_pSndfile, SFC_SET_CLIPPING, NULL, SF_TRUE) ; // Strings passed to and retrieved from sf_get_string/sf_set_string are assumed to be utf-8. // However, while formats like Ogg/Vorbis and FLAC fully support utf-8, others like WAV and // AIFF officially only support ASCII. Writing utf-8 strings to WAV and AIF files with // libsndfile will work when read back with libsndfile, but may not work with other programs. int ret; if (!m_metaDataTitle.isEmpty()) { ret = sf_set_string(m_pSndfile, SF_STR_TITLE, m_metaDataTitle.toAscii().constData()); if (ret != 0) { qWarning("libsndfile error: %s", sf_error_number(ret)); } } if (!m_metaDataArtist.isEmpty()) { ret = sf_set_string(m_pSndfile, SF_STR_ARTIST, m_metaDataArtist.toAscii().constData()); if (ret != 0) { qWarning("libsndfile error: %s", sf_error_number(ret)); } } if (!m_metaDataAlbum.isEmpty()) { int strType = SF_STR_ALBUM; if (m_sfInfo.format == SF_FORMAT_AIFF) { // There is no AIFF text chunk for "Album". But libsndfile is able to // write the SF_STR_COMMENT string into the text chunk with id "ANNO". strType = SF_STR_COMMENT; } ret = sf_set_string(m_pSndfile, strType, m_metaDataAlbum.toAscii().constData()); if (ret != 0) { qWarning("libsndfile error: %s", sf_error_number(ret)); } } }
int Soundfile::close() { int status = 0; if (sndfile) { status = sf_close(sndfile); if (status) { std::cerr << sf_error_number(status) << std::endl; } } initialize(); return status; }
int pa_sndfile_read_sample_spec(SNDFILE *sf, pa_sample_spec *ss) { SF_INFO sfi; int sf_errno; pa_assert(sf); pa_assert(ss); pa_zero(sfi); if ((sf_errno = sf_command(sf, SFC_GET_CURRENT_SF_INFO, &sfi, sizeof(sfi)))) { pa_log_error("sndfile: %s", sf_error_number(sf_errno)); return -1; } switch (sfi.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_16: case SF_FORMAT_PCM_U8: case SF_FORMAT_PCM_S8: ss->format = PA_SAMPLE_S16NE; break; case SF_FORMAT_PCM_24: ss->format = PA_SAMPLE_S24NE; break; case SF_FORMAT_PCM_32: ss->format = PA_SAMPLE_S32NE; break; case SF_FORMAT_ULAW: ss->format = PA_SAMPLE_ULAW; break; case SF_FORMAT_ALAW: ss->format = PA_SAMPLE_ALAW; break; case SF_FORMAT_FLOAT: case SF_FORMAT_DOUBLE: default: ss->format = PA_SAMPLE_FLOAT32NE; break; } ss->rate = (uint32_t) sfi.samplerate; ss->channels = (uint8_t) sfi.channels; if (!pa_sample_spec_valid(ss)) return -1; return 0; }
static const char *GuessSndFile (char *buf, int len) { SF_VIRTUAL_IO io; io.get_filelen = dummy_vio_get_filelen; io.seek = dummy_vio_seek; io.read = dummy_vio_read; io.write = dummy_vio_write; io.tell = dummy_vio_tell; struct dummy_file file; file.buffer = buf; file.length = len; file.curpos = 0; SF_INFO info; memset(&info, 0, sizeof(SF_INFO)); SNDFILE* sndfile = sf_open_virtual (&io, SFM_READ, &info, &file); if( sndfile == NULL ) { int err = sf_error(NULL); fprintf(stderr, "Error occurred: %s\n", sf_error_number(err)); switch(err) { case SF_ERR_UNRECOGNISED_FORMAT: case SF_ERR_UNSUPPORTED_ENCODING: sf_close(sndfile); return NULL; case SF_ERR_SYSTEM: case SF_ERR_MALFORMED_FILE: default: sf_close(sndfile); return QUE_STRING; break; } } else { sf_close(sndfile); SF_FORMAT_INFO format_info; format_info.format = info.format; int ret = sf_command (NULL /* sndfile */, SFC_GET_FORMAT_INFO, &format_info, sizeof(SF_FORMAT_INFO)) ; /* fprintf(stderr, "%s [%s]\n", format_info.name, format_info.extension); */ return format_info.name; } return NULL; }
std::string AudioFileSndfile::sndfileError(int errorNumber, const std::string& userMessage) const { const std::string libraryMessage = sf_error_number(errorNumber); char logInfo[LOGINFO_MAX_SIZE]; sf_command(_handle.get(), SFC_GET_LOG_INFO, logInfo, LOGINFO_MAX_SIZE); LOG(INFO, "Library error detailed information" << "\n\n" << "Sound file: " << _path << '\n' << "Library reports: " << libraryMessage << '\n' << "Library version: " << sf_version_string() << '\n' << "Library log follows:\n" << logInfo); return userMessage + ": " + libraryMessage; }
bool SoundBuffer::LoadFromFile(const std::string& filePath) { SF_INFO soundInfo; #if defined(UTH_SYSTEM_ANDROID) AAsset* asset = FileReader::loadSound(filePath); SF_VIRTUAL_IO virtualIO; virtualIO.get_filelen = &FileReader::getAssetLength; virtualIO.seek = &FileReader::seekAsset; virtualIO.read = &FileReader::readAsset; virtualIO.tell = &FileReader::tellAsset; SNDFILE* file = sf_open_virtual(&virtualIO, SFM_READ, &soundInfo, asset); #elif defined(UTH_SYSTEM_WINDOWS) SNDFILE* file = sf_open(("assets/" + filePath).c_str(), SFM_READ, &soundInfo); #endif if (!file) { int error = sf_error(file); WriteError("Failed to open sound file, error &d", file, error); WriteError(sf_error_number(error)); } WriteLog("Frames: %d\n" , soundInfo.frames); WriteLog("Samplerae: %d\n" , soundInfo.samplerate); WriteLog("Channels: %d\n" , soundInfo.channels); WriteLog("Format: %d\n" , soundInfo.format); m_soundInfo.frames = static_cast<int>(soundInfo.frames * soundInfo.channels); m_soundInfo.channels = soundInfo.channels; m_soundInfo.sampleRate = soundInfo.samplerate; m_soundInfo.soundBuffer = new short[m_soundInfo.frames]; sf_read_short(file, m_soundInfo.soundBuffer, m_soundInfo.frames); sf_close(file); return true; }
static bool stop_writing(void){ char temp[1024]; bool ret; int close_result = sf_close(g_sndfile); if(close_result==0) ret = true; else ret= false; if(ret==false) sprintf(temp,"Unable to save \"%s\": \"%s\".", g_filename, sf_error_number(close_result)); else if(g_saving_was_successful==false) sprintf(temp,"\"%s\" was saved, but with errors.", g_filename); else sprintf(temp,"\"%s\" successfully saved.", g_filename); SOUNDFILESAVERGUI_stop(temp); return ret; }
static void multichunk_test_helper (const char *filename, int format, const char * testdata [], size_t testdata_len) { SNDFILE *file ; SF_INFO sfinfo ; SF_CHUNK_INFO chunk_info ; SF_CHUNK_ITERATOR * iterator ; uint32_t length_before [16] ; int err, allow_fd ; size_t i ; exit_if_true ( ARRAY_LEN (length_before) < testdata_len, "\n\nLine %d : Bad array length.\n\n", __LINE__ ) ; sfinfo.samplerate = 44100 ; sfinfo.channels = 1 ; sfinfo.frames = 0 ; sfinfo.format = format ; switch (format & SF_FORMAT_SUBMASK) { case SF_FORMAT_ALAC_16 : allow_fd = SF_FALSE ; break ; default : allow_fd = SF_TRUE ; break ; } ; file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ; /* Set up the chunk to write. */ for (i = 0 ; i < testdata_len ; i++) { memset (&chunk_info, 0, sizeof (chunk_info)) ; snprintf (chunk_info.id, sizeof (chunk_info.id), "Test") ; chunk_info.id_size = 4 ; chunk_info.data = strdup (testdata [i]) ; chunk_info.datalen = strlen (chunk_info.data) ; length_before [i] = chunk_info.datalen ; err = sf_set_chunk (file, &chunk_info) ; exit_if_true ( err != SF_ERR_NO_ERROR, "\n\nLine %d : sf_set_chunk returned for testdata[%d] '%s' : %s\n\n", __LINE__, (int) i, testdata [i], sf_error_number (err) ) ; memset (chunk_info.data, 0, chunk_info.datalen) ; free (chunk_info.data) ; } sf_close (file) ; file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ; memset (&chunk_info, 0, sizeof (chunk_info)) ; snprintf (chunk_info.id, sizeof (chunk_info.id), "Test") ; chunk_info.id_size = 4 ; iterator = sf_get_chunk_iterator (file, &chunk_info) ; i = 0 ; while (iterator) { memset (&chunk_info, 0, sizeof (chunk_info)) ; err = sf_get_chunk_size (iterator, &chunk_info) ; exit_if_true ( i > testdata_len, "\n\nLine %d : iterated to chunk #%d, but only %d chunks have been written\n\n", __LINE__, (int) i, (int) testdata_len ) ; exit_if_true ( err != SF_ERR_NO_ERROR, "\n\nLine %d : sf_get_chunk_size returned for testdata[%d] '%s' : %s\n\n", __LINE__, (int) i, testdata [i], sf_error_number (err) ) ; exit_if_true ( length_before [i] > chunk_info.datalen || chunk_info.datalen - length_before [i] > 4, "\n\nLine %d : testdata[%d] '%s' : Bad chunk length %u (previous length %u)\n\n", __LINE__, (int) i, testdata [i], chunk_info.datalen, length_before [i] ) ; chunk_info.data = malloc (chunk_info.datalen) ; err = sf_get_chunk_data (iterator, &chunk_info) ; exit_if_true ( err != SF_ERR_NO_ERROR, "\n\nLine %d : sf_get_chunk_size returned for testdata[%d] '%s' : %s\n\n", __LINE__, (int) i, testdata [i], sf_error_number (err) ) ; exit_if_true ( 4 != chunk_info.id_size, "\n\nLine %d : testdata[%d] : Bad ID length %u (previous length %u)\n\n", __LINE__, (int) i, chunk_info.id_size, 4 ) ; exit_if_true ( memcmp ("Test", chunk_info.id, 4), "\n\nLine %d : ID compare failed at %d.\n %s\n %s\n\n", __LINE__, (int) i, "Test", (char*) chunk_info.id ) ; exit_if_true ( memcmp (testdata [i], chunk_info.data, length_before [i]), "\n\nLine %d : Data compare failed at %d.\n %s\n %s\n\n", __LINE__, (int) i, testdata [i], (char*) chunk_info.data ) ; free (chunk_info.data) ; iterator = sf_next_chunk_iterator (iterator) ; i++ ; } sf_close (file) ; unlink (filename) ; } /* multichunk_test_helper */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { //-------------------------------------------- // VARIABLES //-------------------------------------------- //-- // samples and rate //-- // NOTE: this includes the samples array pointer, number of channels and samples, and rate void *X; int n, ch, r, e; //-- // output file name //-- char *f; int len; //-- // format and encoding //-- int fmt_code, enc_code; //-- // libsndfile structures //-- SNDFILE *out_file; SF_INFO out_info; mxClassID cls; //-------------------------------------------- // INPUT //-------------------------------------------- // TODO: add some check on the number of channels and samples //-------------------------------- // samples and rate //-------------------------------- X = mxGetPr(prhs[0]); cls = mxGetClassID(prhs[0]); n = mxGetN(prhs[0]); ch = mxGetM(prhs[0]); r = (int) mxGetScalar(prhs[1]); //-------------------------------- // output file //-------------------------------- len = mxGetM(prhs[2]) * mxGetN(prhs[2]) + 1; f = mxCalloc(len, sizeof(char)); mxGetString(prhs[2], f, len); //-------------------------------- // format and encoding //-------------------------------- // NOTE: although we could extract the format from the file name it it easier in MATLAB fmt_code = (int) mxGetScalar(prhs[3]); enc_code = (int) mxGetScalar(prhs[4]); //-------------------------------------------- // COMPUTATION //-------------------------------------------- //-------------------------------- // fill info structure //-------------------------------- out_info.frames = n; out_info.channels = ch; out_info.samplerate = r; out_info.sections = 1; out_info.seekable = 1; // NOTE: look at 'sndfile.h' for the meanings of these switch (fmt_code) { case 0: fmt_code = SF_FORMAT_WAV; break; case 1: fmt_code = SF_FORMAT_AIFF; break; case 2: fmt_code = SF_FORMAT_AU; break; case 3: fmt_code = SF_FORMAT_W64; break; case 4: fmt_code = SF_FORMAT_FLAC; break; default: mexErrMsgTxt("Unsupported major file format."); } // NOTE: look at 'sndfile.h' for the meanings of these switch (enc_code) { case 0: if (fmt_code == SF_FORMAT_AU) { mexErrMsgTxt("Unsupported encoding for major file format."); } enc_code = SF_FORMAT_PCM_U8; break; case 1: if ((fmt_code == SF_FORMAT_WAV) || (fmt_code == SF_FORMAT_WAV)) { mexErrMsgTxt("Unsupported encoding for major file format."); } enc_code = SF_FORMAT_PCM_S8; break; case 2: enc_code = SF_FORMAT_PCM_16; break; case 3: enc_code = SF_FORMAT_PCM_24; break; case 4: enc_code = SF_FORMAT_PCM_32; break; case 5: enc_code = SF_FORMAT_FLOAT; break; case 6: enc_code = SF_FORMAT_DOUBLE; break; case 7: enc_code = SF_FORMAT_ULAW; break; case 8: enc_code = SF_FORMAT_ALAW; break; case 9: if ((fmt_code == SF_FORMAT_AIFF) || (fmt_code == SF_FORMAT_AU)) { mexErrMsgTxt("Unsupported encoding for major file format."); } enc_code = SF_FORMAT_IMA_ADPCM; break; case 10: if ((fmt_code == SF_FORMAT_AIFF) || (fmt_code == SF_FORMAT_AU)) { mexErrMsgTxt("Unsupported encoding for major file format."); } enc_code = SF_FORMAT_MS_ADPCM; break; case 11: if (fmt_code == SF_FORMAT_AU) { mexErrMsgTxt("Unsupported encoding for major file format."); } enc_code = SF_FORMAT_GSM610; break; default: mexErrMsgTxt("Unsupported encoding."); } out_info.format = fmt_code | enc_code; if (!sf_format_check(&out_info)) mexErrMsgTxt("failed format check."); //-------------------------------- // create output file //-------------------------------- //-- // open output file (create if needed) //-- out_file = sf_open (f, SFM_WRITE, &out_info); if (out_file == NULL) { // grab log buffer (very informative about errors) char buffer [2048] ; sf_command (out_file, SFC_GET_LOG_INFO, buffer, sizeof (buffer)) ; mexPrintf("%s\n", buffer); // there must be an error, display it, and break. mexErrMsgTxt(sf_error_number(sf_error(out_file))) ; } //-- // write samples to output file //-- // NOTE: set normalization to true, this assumes samples are in the -1 to 1 range switch (cls){ case (mxDOUBLE_CLASS): sf_command (out_file, SFC_SET_NORM_DOUBLE, NULL, SF_TRUE); sf_writef_double (out_file, (double *) X, n); break; case (mxSINGLE_CLASS): sf_command (out_file, SFC_SET_NORM_FLOAT, NULL, SF_TRUE); sf_writef_float (out_file, (float *) X, n); break; default: mexErrMsgTxt("Unsupported class.\n"); } //-- // close file //-- sf_close (out_file); }
static int CloseSndFile(Sound *s, Tcl_Interp *interp, Tcl_Channel *ch) { /* fprintf(stderr, "CloseSndFile\n"); */ int err = sf_close((SNDFILE*) *ch); if (err != 0) { Tcl_AppendResult(interp, "SNDFILE: error closing file: ", Snack_GetSoundFilename(s), "\n", sf_error_number(err), NULL); } *ch = NULL; return TCL_OK; }
bool SFB::Audio::LibsndfileDecoder::_Open(CFErrorRef *error) { // Set up the virtual IO function pointers SF_VIRTUAL_IO virtualIO; virtualIO.get_filelen = my_sf_vio_get_filelen; virtualIO.seek = my_sf_vio_seek; virtualIO.read = my_sf_vio_read; virtualIO.write = nullptr; virtualIO.tell = my_sf_vio_tell; // Open the input file mFile = unique_SNDFILE_ptr(sf_open_virtual(&virtualIO, SFM_READ, &mFileInfo, this), sf_close); if(!mFile) { LOGGER_ERR("org.sbooth.AudioEngine.Decoder.Libsndfile", "sf_open_virtual failed: " << sf_error_number(sf_error(nullptr))); if(nullptr != error) { SFB::CFString description(CFCopyLocalizedString(CFSTR("The format of the file “%@” was not recognized."), "")); SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("File Format Not Recognized"), "")); SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); *error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion); } return false; } // Generate interleaved PCM output mFormat.mFormatID = kAudioFormatLinearPCM; mFormat.mSampleRate = mFileInfo.samplerate; mFormat.mChannelsPerFrame = (UInt32)mFileInfo.channels; int subFormat = SF_FORMAT_SUBMASK & mFileInfo.format; // 8-bit PCM will be high-aligned in shorts if(SF_FORMAT_PCM_U8 == subFormat) { mFormat.mFormatFlags = kAudioFormatFlagIsAlignedHigh; mFormat.mBitsPerChannel = 8; mFormat.mBytesPerPacket = sizeof(short) * mFormat.mChannelsPerFrame; mFormat.mFramesPerPacket = 1; mFormat.mBytesPerFrame = mFormat.mBytesPerPacket * mFormat.mFramesPerPacket; mReadMethod = ReadMethod::Short; } else if(SF_FORMAT_PCM_S8 == subFormat) { mFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsAlignedHigh; mFormat.mBitsPerChannel = 8; mFormat.mBytesPerPacket = sizeof(short) * mFormat.mChannelsPerFrame; mFormat.mFramesPerPacket = 1; mFormat.mBytesPerFrame = mFormat.mBytesPerPacket * mFormat.mFramesPerPacket; mReadMethod = ReadMethod::Short; } // 16-bit PCM else if(SF_FORMAT_PCM_16 == subFormat) { mFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; mFormat.mBitsPerChannel = 16; mFormat.mBytesPerPacket = (mFormat.mBitsPerChannel / 8) * mFormat.mChannelsPerFrame; mFormat.mFramesPerPacket = 1; mFormat.mBytesPerFrame = mFormat.mBytesPerPacket * mFormat.mFramesPerPacket; mReadMethod = ReadMethod::Short; } // 24-bit PCM will be high-aligned in ints else if(SF_FORMAT_PCM_24 == subFormat) { mFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsAlignedHigh; mFormat.mBitsPerChannel = 24; mFormat.mBytesPerPacket = sizeof(int) * mFormat.mChannelsPerFrame; mFormat.mFramesPerPacket = 1; mFormat.mBytesPerFrame = mFormat.mBytesPerPacket * mFormat.mFramesPerPacket; mReadMethod = ReadMethod::Int; } // 32-bit PCM else if(SF_FORMAT_PCM_32 == subFormat) { mFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; mFormat.mBitsPerChannel = 32; mFormat.mBytesPerPacket = (mFormat.mBitsPerChannel / 8) * mFormat.mChannelsPerFrame; mFormat.mFramesPerPacket = 1; mFormat.mBytesPerFrame = mFormat.mBytesPerPacket * mFormat.mFramesPerPacket; mReadMethod = ReadMethod::Int; } // Floating point formats else if(SF_FORMAT_FLOAT == subFormat) { mFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked; mFormat.mBitsPerChannel = 8 * sizeof(float); mFormat.mBytesPerPacket = (mFormat.mBitsPerChannel / 8) * mFormat.mChannelsPerFrame; mFormat.mFramesPerPacket = 1; mFormat.mBytesPerFrame = mFormat.mBytesPerPacket * mFormat.mFramesPerPacket; mReadMethod = ReadMethod::Float; } else if(SF_FORMAT_DOUBLE == subFormat) { mFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked; mFormat.mBitsPerChannel = 8 * sizeof(double); mFormat.mBytesPerPacket = (mFormat.mBitsPerChannel / 8) * mFormat.mChannelsPerFrame; mFormat.mFramesPerPacket = 1; mFormat.mBytesPerFrame = mFormat.mBytesPerPacket * mFormat.mFramesPerPacket; mReadMethod = ReadMethod::Double; } // Everything else will be converted to 32-bit float else { mFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked; mFormat.mBitsPerChannel = 8 * sizeof(float); mFormat.mBytesPerPacket = (mFormat.mBitsPerChannel / 8) * mFormat.mChannelsPerFrame; mFormat.mFramesPerPacket = 1; mFormat.mBytesPerFrame = mFormat.mBytesPerPacket * mFormat.mFramesPerPacket; mReadMethod = ReadMethod::Float; } mFormat.mReserved = 0; // Set up the source format mSourceFormat.mFormatID = 'SNDF'; mSourceFormat.mSampleRate = mFileInfo.samplerate; mSourceFormat.mChannelsPerFrame = (UInt32)mFileInfo.channels; switch(subFormat) { case SF_FORMAT_PCM_U8: mSourceFormat.mBitsPerChannel = 8; break; case SF_FORMAT_PCM_S8: mSourceFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger; mSourceFormat.mBitsPerChannel = 8; break; case SF_FORMAT_PCM_16: mSourceFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger; mSourceFormat.mBitsPerChannel = 16; break; case SF_FORMAT_PCM_24: mSourceFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger; mSourceFormat.mBitsPerChannel = 24; break; case SF_FORMAT_PCM_32: mSourceFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger; mSourceFormat.mBitsPerChannel = 32; break; case SF_FORMAT_FLOAT: mSourceFormat.mFormatFlags = kAudioFormatFlagIsFloat; mSourceFormat.mBitsPerChannel = 32; break; case SF_FORMAT_DOUBLE: mSourceFormat.mFormatFlags = kAudioFormatFlagIsFloat; mSourceFormat.mBitsPerChannel = 64; break; } return true; }
const char* audiofile_exception::what() const throw() { return sf_error_number(code); }
SNDFILE * test_open_file_or_die (const char *filename, int mode, SF_INFO *sfinfo, int allow_fd, int line_num) { static int count = 0 ; SNDFILE *file ; const char *modestr, *func_name ; int oflags = 0, omode = 0, err ; /* ** Need to test both sf_open() and sf_open_fd(). ** Do so alternately. */ switch (mode) { case SFM_READ : modestr = "SFM_READ" ; oflags = O_RDONLY | O_BINARY ; omode = 0 ; break ; case SFM_WRITE : modestr = "SFM_WRITE" ; oflags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ; omode = S_IRUSR | S_IWUSR | S_IRGRP ; break ; case SFM_RDWR : modestr = "SFM_RDWR" ; oflags = O_RDWR | O_CREAT | O_BINARY ; omode = S_IRUSR | S_IWUSR | S_IRGRP ; break ; default : printf ("\n\nLine %d: Bad mode.\n", line_num) ; fflush (stdout) ; exit (1) ; } ; if (OS_IS_WIN32) { /* Windows does not understand and ignores the S_IRGRP flag, but Wine ** gives a run time warning message, so just clear it. */ omode &= ~S_IRGRP ; } ; if (allow_fd && ((++count) & 1) == 1) { int fd ; /* Only use the three argument open() function if omode != 0. */ fd = (omode == 0) ? open (filename, oflags) : open (filename, oflags, omode) ; if (fd < 0) { printf ("\n\n%s : open failed : %s\n", __func__, strerror (errno)) ; exit (1) ; } ; func_name = "sf_open_fd" ; file = sf_open_fd (fd, mode, sfinfo, SF_TRUE) ; } else { func_name = "sf_open" ; file = sf_open (filename, mode, sfinfo) ; } ; if (file == NULL) { printf ("\n\nLine %d: %s (%s) failed : %s\n\n", line_num, func_name, modestr, sf_strerror (NULL)) ; dump_log_buffer (file) ; exit (1) ; } ; err = sf_error (file) ; if (err != SF_ERR_NO_ERROR) { printf ("\n\nLine %d : sf_error : %s\n\n", line_num, sf_error_number (err)) ; dump_log_buffer (file) ; exit (1) ; } ; return file ; } /* test_open_file_or_die */
SNDFILE * test_open_file_or_die (const char *filename, int mode, SF_INFO *sfinfo, int allow_fd, int line_num) { static int count = 0 ; SNDFILE *file ; const char *modestr, *func_name ; int oflags = 0, omode = 0, err ; /* ** Need to test both sf_open() and sf_open_fd(). ** Do so alternately. */ switch (mode) { case SFM_READ : modestr = "SFM_READ" ; oflags = O_RDONLY | O_BINARY ; omode = 0 ; break ; case SFM_WRITE : modestr = "SFM_WRITE" ; oflags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ; omode = S_IRUSR | S_IWUSR | S_IRGRP ; break ; case SFM_RDWR : modestr = "SFM_RDWR" ; oflags = O_RDWR | O_CREAT | O_BINARY ; omode = S_IRUSR | S_IWUSR | S_IRGRP ; break ; default : printf ("\n\nLine %d: Bad mode.\n", line_num) ; fflush (stdout) ; exit (1) ; } ; if (OS_IS_WIN32) { /* Windows doesn't support Unix file permissions so set it to zero. */ omode = 0 ; } ; if (allow_fd && ((++count) & 1) == 1) { int fd ; fd = open (filename, oflags, omode) ; if (fd < 0) { perror ("open") ; exit (1) ; } ; func_name = "sf_open_fd" ; file = sf_open_fd (fd, mode, sfinfo, SF_TRUE) ; } else { func_name = "sf_open" ; file = sf_open (filename, mode, sfinfo) ; } ; if (file == NULL) { printf ("\n\nLine %d: %s (%s) failed : %s\n\n", line_num, func_name, modestr, sf_strerror (NULL)) ; dump_log_buffer (file) ; exit (1) ; } ; err = sf_error (file) ; if (err != SF_ERR_NO_ERROR) { printf ("\n\nLine %d : sf_error : %s\n\n", line_num, sf_error_number (err)) ; dump_log_buffer (file) ; exit (1) ; } ; return file ; } /* test_open_file_or_die */
bool EngineRecord::openFile() { // Unfortunately, we cannot use QFile for writing WAV and AIFF audio. if (m_encoding == ENCODING_WAVE || m_encoding == ENCODING_AIFF){ unsigned long samplerate = m_pSamplerate->get(); // set sfInfo m_sfInfo.samplerate = samplerate; m_sfInfo.channels = 2; if (m_encoding == ENCODING_WAVE) m_sfInfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; else m_sfInfo.format = SF_FORMAT_AIFF | SF_FORMAT_PCM_16; // Creates a new WAVE or AIFF file and writes header information. #ifdef __WINDOWS__ LPCWSTR lpcwFilename = (LPCWSTR)m_fileName.utf16(); //Pointer valid until string changed m_pSndfile = sf_wchar_open( lpcwFilename, SFM_WRITE, &m_sfInfo); #else QByteArray qbaFilename = m_fileName.toUtf8(); m_pSndfile = sf_open(qbaFilename.data(), SFM_WRITE, &m_sfInfo); #endif if (m_pSndfile) { sf_command(m_pSndfile, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ; // Set meta data int ret; ret = sf_set_string(m_pSndfile, SF_STR_TITLE, m_baTitle.data()); if(ret != 0) qDebug("libsndfile: %s", sf_error_number(ret)); ret = sf_set_string(m_pSndfile, SF_STR_ARTIST, m_baAuthor.data()); if(ret != 0) qDebug("libsndfile: %s", sf_error_number(ret)); ret = sf_set_string(m_pSndfile, SF_STR_COMMENT, m_baAlbum.data()); if(ret != 0) qDebug("libsndfile: %s", sf_error_number(ret)); } } else { // We can use a QFile to write compressed audio. if (m_pEncoder) { m_file.setFileName(m_fileName); m_file.open(QIODevice::WriteOnly); if (m_file.handle() != -1) { m_dataStream.setDevice(&m_file); } } else { return false; } } // Check if file is really open. if (!fileOpen()) { ErrorDialogProperties* props = ErrorDialogHandler::instance()->newDialogProperties(); props->setType(DLG_WARNING); props->setTitle(tr("Recording")); props->setText("<html>"+tr("Could not create audio file for recording!") +"<p>"+tr("Ensure there is enough free disk space and you have write permission for the Recordings folder.") +"<p>"+tr("You can change the location of the Recordings folder in Preferences > Recording.") +"</p></html>"); ErrorDialogHandler::instance()->requestErrorDialog(props); return false; } return true; }
double sound_save( LVAL snd_expr, long n, unsigned char *filename, long format, long mode, long bits, long swap, double *sr, long *nchans, double *duration, LVAL play) { LVAL result; float *buf; long ntotal; double max_sample; SNDFILE *sndfile = NULL; SF_INFO sf_info; PaStream *audio_stream = NULL; if (SAFE_NYQUIST) play = FALSE; gc(); memset(&sf_info, 0, sizeof(sf_info)); sf_info.format = lookup_format(format, mode, bits, swap); result = xleval(snd_expr); /* BE CAREFUL - DO NOT ALLOW GC TO RUN WHILE RESULT IS UNPROTECTED */ if (vectorp(result)) { /* make sure all elements are of type a_sound */ long i = getsize(result); *nchans = sf_info.channels = i; while (i > 0) { i--; if (!exttypep(getelement(result, i), a_sound)) { xlerror("sound_save: array has non-sound element", result); } } /* assume all are the same: */ *sr = sf_info.samplerate = ROUND(getsound(getelement(result, 0))->sr); /* note: if filename is "", then don't write file; therefore, * write the file if (filename[0]) */ if (filename[0]) { sndfile = NULL; if (ok_to_open((char *) filename, "wb")) sndfile = sf_open((char *) filename, SFM_WRITE, &sf_info); if (sndfile) { /* use proper scale factor: 8000 vs 7FFF */ sf_command(sndfile, SFC_SET_CLIPPING, NULL, SF_TRUE); } } if (play) play = prepare_audio(play, &sf_info, &audio_stream); if ((buf = (float *) malloc(max_sample_block_len * sf_info.channels * sizeof(float))) == NULL) { xlabort("snd_save -- couldn't allocate memory"); } max_sample = sound_save_array(result, n, &sf_info, sndfile, buf, &ntotal, audio_stream); *duration = ntotal / *sr; if (sndfile) sf_close(sndfile); if (play != NIL) finish_audio(audio_stream); } else if (exttypep(result, a_sound)) { *nchans = sf_info.channels = 1; sf_info.samplerate = ROUND((getsound(result))->sr); *sr = sf_info.samplerate; if (filename[0]) { sndfile = NULL; if (ok_to_open((char *) filename, "wb")) { sndfile = sf_open((char *) filename, SFM_WRITE, &sf_info); if (sndfile) { /* use proper scale factor: 8000 vs 7FFF */ sf_command(sndfile, SFC_SET_CLIPPING, NULL, SF_TRUE); } else { char error[240]; sprintf(error, "snd_save -- %s", sf_error_number(sf_error(sndfile))); xlabort(error); } } else { xlabort("snd_save -- write not permitted by -W option"); } } if (play) play = prepare_audio(play, &sf_info, &audio_stream); if ((buf = (float *) malloc(max_sample_block_len * sizeof(float))) == NULL) { xlabort("snd_save -- couldn't allocate memory"); } max_sample = sound_save_sound(result, n, &sf_info, sndfile, buf, &ntotal, audio_stream); *duration = ntotal / *sr; if (sndfile) sf_close(sndfile); if (play != NIL) finish_audio(audio_stream); } else { xlerror("sound_save: expression did not return a sound", result); max_sample = 0.0; } free(buf); return max_sample; }
static void wav_subchunk_test (size_t chunk_size) { SNDFILE * file ; SF_INFO sfinfo ; SF_CHUNK_INFO chunk_info ; char filename [256] ; char chunk_data [10240] ; short audio [16] ; int err, value ; snprintf (filename, sizeof (filename), "subchunk_%04d.wav", (int) chunk_size) ; print_test_name (__func__, filename) ; exit_if_true (sizeof (chunk_data) < chunk_size, "\n\nLine %d : sizeof (data) < chunk_size\n\n", __LINE__) ; memset (chunk_data, 53, sizeof (chunk_data)) ; chunk_data [chunk_size] = 0 ; /* Fill in the chunk data. */ value = MAKE_MARKER ('a', 'd', 't', 'l') ; memcpy (chunk_data, &value, sizeof (value)) ; value = MAKE_MARKER ('n', 'o', 't', 'e') ; memcpy (chunk_data + 4, &value, sizeof (value)) ; value = H2LE_32 (chunk_size - 12) ; memcpy (chunk_data + 8, &value, sizeof (value)) ; sfinfo.samplerate = 44100 ; sfinfo.channels = 1 ; sfinfo.frames = 0 ; sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 ; file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; /* Set up the chunk to write. */ memset (&chunk_info, 0, sizeof (chunk_info)) ; snprintf (chunk_info.id, sizeof (chunk_info.id), "LIST") ; chunk_info.id_size = 4 ; chunk_info.data = chunk_data ; chunk_info.datalen = chunk_size ; err = sf_set_chunk (file, &chunk_info) ; exit_if_true ( err != SF_ERR_NO_ERROR, "\n\nLine %d : sf_set_chunk returned for testdata : %s\n\n", __LINE__, sf_error_number (err) ) ; memset (chunk_info.data, 0, chunk_info.datalen) ; /* Add some audio data. */ memset (audio, 0, sizeof (audio)) ; sf_write_short (file, audio, ARRAY_LEN (audio)) ; sf_close (file) ; file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ; exit_if_true ( sfinfo.frames != ARRAY_LEN (audio), "\n\nLine %d : Incorrect sample count (%d should be %d)\n", __LINE__, (int) sfinfo.frames, (int) ARRAY_LEN (audio) ) ; if (chunk_size < 512) check_log_buffer_or_die (file, __LINE__) ; sf_close (file) ; unlink (filename) ; puts ("ok") ; } /* wav_subchunk_test */
static void stdin_test (int typemajor, int count) { static short data [BUFFER_LEN] ; SNDFILE *file ; SF_INFO sfinfo ; int k, total, err ; if (typemajor == SF_FORMAT_RAW) { sfinfo.samplerate = 44100 ; sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16 ; sfinfo.channels = 1 ; sfinfo.frames = 0 ; } else memset (&sfinfo, 0, sizeof (sfinfo)) ; #if USE_WINDOWS_API if ((file = sf_open_fd (fileno (stdin), SFM_READ, &sfinfo, SF_TRUE)) == NULL) #else if ((file = sf_open_fd (STDIN_FILENO, SFM_READ, &sfinfo, SF_TRUE)) == NULL) #endif { fprintf (stderr, "sf_open_fd failed with error : ") ; puts (sf_strerror (NULL)) ; dump_log_buffer (NULL) ; exit (1) ; } ; err = sf_error (file) ; if (err != SF_ERR_NO_ERROR) { printf ("Line %d : unexpected error : %s\n", __LINE__, sf_error_number (err)) ; exit (1) ; } ; if ((sfinfo.format & SF_FORMAT_TYPEMASK) != typemajor) { fprintf (stderr, "\n\nError : File type doesn't match.\n") ; exit (1) ; } ; if (sfinfo.samplerate != 44100) { fprintf (stderr, "\n\nError : Sample rate (%d) should be 44100\n", sfinfo.samplerate) ; exit (1) ; } ; if (sfinfo.channels != 1) { fprintf (stderr, "\n\nError : Channels (%d) should be 1\n", sfinfo.channels) ; exit (1) ; } ; if (sfinfo.frames < count) { fprintf (stderr, "\n\nError : Sample count (%ld) should be %d\n", (long) sfinfo.frames, count) ; exit (1) ; } ; total = 0 ; while ((k = sf_read_short (file, data + total, BUFFER_LEN - total)) > 0) total += k ; if (total != count) { fprintf (stderr, "\n\nError : Expected %d frames, read %d.\n", count, total) ; exit (1) ; } ; for (k = 0 ; k < total ; k++) if (data [k] != PIPE_INDEX (k)) { printf ("\n\nError : data [%d] == %d, should have been %d.\n\n", k, data [k], k) ; exit (1) ; } ; sf_close (file) ; return ; } /* stdin_test */
static void chunk_test_helper (const char *filename, int typemajor, const char * testdata) { SNDFILE *file ; SF_INFO sfinfo ; SF_CHUNK_INFO chunk_info ; uint32_t length_before ; int err ; sfinfo.samplerate = 44100 ; sfinfo.channels = 1 ; sfinfo.frames = 0 ; switch (typemajor) { case SF_FORMAT_OGG : sfinfo.format = typemajor | SF_FORMAT_VORBIS ; break ; default : sfinfo.format = typemajor | SF_FORMAT_PCM_16 ; break ; } ; file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; /* Set up the chunk to write. */ memset (&chunk_info, 0, sizeof (chunk_info)) ; snprintf (chunk_info.id, sizeof (chunk_info.id), "Test") ; chunk_info.id_size = 4 ; chunk_info.data = strdup (testdata) ; chunk_info.datalen = strlen (chunk_info.data) ; length_before = chunk_info.datalen ; err = sf_set_chunk (file, &chunk_info) ; exit_if_true ( err != SF_ERR_NO_ERROR, "\n\nLine %d : sf_set_chunk returned for testdata '%s' : %s\n", __LINE__, testdata, sf_error_number (err) ) ; memset (chunk_info.data, 0, chunk_info.datalen) ; free (chunk_info.data) ; sf_close (file) ; file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ; memset (&chunk_info, 0, sizeof (chunk_info)) ; snprintf (chunk_info.id, sizeof (chunk_info.id), "Test") ; chunk_info.id_size = 4 ; err = sf_get_chunk_size (file, &chunk_info) ; exit_if_true ( err != SF_ERR_NO_ERROR, "\n\nLine %d : sf_get_chunk_size returned for testdata '%s' : %s", __LINE__, testdata, sf_error_number (err) ) ; exit_if_true ( length_before > chunk_info.datalen || chunk_info.datalen - length_before > 4, "\n\nLine %d : testdata '%s' : Bad chunk length %u (previous length %u)\n", __LINE__, testdata, chunk_info.datalen, length_before ) ; chunk_info.data = malloc (chunk_info.datalen) ; err = sf_get_chunk_data (file, &chunk_info) ; exit_if_true ( err != SF_ERR_NO_ERROR, "\n\nLine %d : sf_get_chunk_size returned for testdata '%s' : %s", __LINE__, testdata, sf_error_number (err) ) ; exit_if_true ( memcmp (testdata, chunk_info.data, length_before), "\n\nLine %d : Data compare failed.\n %s\n %s\n\n", __LINE__, testdata, (char*) chunk_info.data ) ; free (chunk_info.data) ; sf_close (file) ; unlink (filename) ; } /* chunk_test_helper */