ambix_err_t _ambix_write_uuidchunk(ambix_t*ax, const void*data, int64_t datasize) { #if defined HAVE_SF_SET_CHUNK && defined (HAVE_SF_CHUNK_INFO) int err ; SF_CHUNK_INFO*chunk=&PRIVATE(ax)->sf_chunk; int64_t datasize4 = datasize>>2; if(datasize4*4 < datasize) datasize4++; memset (chunk, 0, sizeof (*chunk)) ; snprintf (chunk->id, sizeof (chunk->id), "uuid") ; chunk->id_size = 4 ; if(chunk->data) free(chunk->data); chunk->data = calloc(datasize4, 4); memcpy(chunk->data, data, datasize); chunk->datalen = datasize ; err = sf_set_chunk (PRIVATE(ax)->sf_file, chunk) ; if(SF_ERR_NO_ERROR != err) return AMBIX_ERR_UNKNOWN; return AMBIX_ERR_SUCCESS; #elif defined HAVE_SF_UUID_INFO SF_UUID_INFO uuid; memcpy(uuid.id, data, 16); uuid.data=(void*)(data+16); uuid.data_size=datasize-16; if(!sf_command(PRIVATE(ax)->sf_file, SFC_SET_UUID, &uuid, sizeof(uuid))) { return AMBIX_ERR_SUCCESS; } #endif return AMBIX_ERR_UNKNOWN; }
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 */
ambix_err_t _ambix_write_chunk(ambix_t*ax, uint32_t id, const void*data, int64_t datasize) { #if defined (HAVE_SF_SET_CHUNK) int err ; int64_t datasize4 = datasize>>2; SF_CHUNK_INFO *chunks = NULL; SF_CHUNK_INFO *chunk = NULL; unsigned int numchunks=(PRIVATE(ax)->sf_numchunks); if(datasize4*4 < datasize) datasize4++; /* (re-)allocate memory for the new chunk - data has to be kept until file closes! */ if (0 == numchunks) { chunks = (SF_CHUNK_INFO*)calloc(1, sizeof(*chunks)); } else { chunks = (SF_CHUNK_INFO*)realloc(PRIVATE(ax)->sf_otherchunks, (numchunks+1)*sizeof(*chunks)); } if (NULL == chunks) return AMBIX_ERR_UNKNOWN; chunk = chunks + numchunks; memset (chunk, 0, sizeof (*chunk)) ; //snprintf (chunk->id, 4, id) ; memcpy(chunk->id, &id, 4); chunk->id_size = 4 ; if(chunk->data) free(chunk->data); chunk->data = calloc(datasize4, 4); memcpy(chunk->data, data, datasize); chunk->datalen = datasize ; err = sf_set_chunk (PRIVATE(ax)->sf_file, chunk); PRIVATE(ax)->sf_numchunks += 1; PRIVATE(ax)->sf_otherchunks = chunks; if(SF_ERR_NO_ERROR != err) return AMBIX_ERR_UNKNOWN; return AMBIX_ERR_SUCCESS; #endif return AMBIX_ERR_UNKNOWN; }
void AudioFileSndfile::flushChunks() { if (_chunksFlushed) { return; } int errorNumber; std::vector<ChunkData> buffer; if (_info.chunkFlags & (1 << ChunkBroadcastInfo)) { buffer = _chunks[ChunkBroadcastInfo]; errorNumber = sf_command(_handle.get(), SFC_SET_BROADCAST_INFO, buffer.data(), int(buffer.size())); if (errorNumber) { SNDFILE_ERROR(errorNumber, "Unable to write broadcast info"); } } if (_info.chunkFlags & (1 << ChunkCartInfo)) { buffer = _chunks[ChunkCartInfo]; errorNumber = sf_command(_handle.get(), SFC_SET_CART_INFO, buffer.data(), int(buffer.size())); if (errorNumber) { SNDFILE_ERROR(errorNumber, "Unable to write cart info"); } } if (_info.chunkFlags & (1 << ChunkCues)) { buffer = _chunks[ChunkCues]; errorNumber = sf_command(_handle.get(), SFC_SET_CUE, buffer.data(), int(buffer.size())); if (errorNumber) { SNDFILE_ERROR(errorNumber, "Unable to write cues"); } } if (_info.chunkFlags & (1 << ChunkInstrument)) { buffer = _chunks[ChunkInstrument]; errorNumber = sf_command(_handle.get(), SFC_SET_INSTRUMENT, buffer.data(), int(buffer.size())); if (errorNumber) { SNDFILE_ERROR(errorNumber, "Unable to write instrument chunk"); } } if (_info.chunkFlags & (1 << ChunkLoopInfo)) { buffer = _chunks[ChunkLoopInfo]; auto li = reinterpret_cast<SF_LOOP_INFO*>(buffer.data()); unsigned flags = 0; if (li->loop_mode == SF_LOOP_FORWARD) { flags |= 0x01; } if (!li->root_key) { flags |= 0x02; } struct { uint32_t flags; uint16_t rootNote; uint16_t wReserved; float fReserved; uint32_t beats; uint16_t time_sig_den; uint16_t time_sig_num; float bpm; } acid = { flags, uint16_t(li->root_key), 0x8000, .0, uint16_t(li->num_beats), uint16_t(li->time_sig_den), uint16_t(li->time_sig_num), float(li->bpm), }; SF_CHUNK_INFO sfci; memset(&sfci, 0, sizeof sfci); strcpy(sfci.id, "acid"); sfci.id_size = 4; sfci.data = &acid; sfci.datalen = sizeof acid; errorNumber = sf_set_chunk(_handle.get(), &sfci); if (errorNumber) { SNDFILE_ERROR(errorNumber, "Unable to write loop info"); } } for (auto it = _rawChunksData.begin(); it != _rawChunksData.end(); ++it) { SF_CHUNK_INFO sfci; memset(&sfci, 0, sizeof sfci); strncpy(sfci.id, it->id.c_str(), sizeof sfci.id); sfci.id_size = it->id.length(); sfci.data = it->data.data(); sfci.datalen = it->data.size(); errorNumber = sf_set_chunk(_handle.get(), &sfci); if (errorNumber) { SNDFILE_ERROR(errorNumber, "Error writing raw chunk"); } } }
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 */
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 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 */