#include <ardour/filesource.h>
#include <ardour/session.h>
#include <ardour/cycle_timer.h>
+#include <ardour/pcm_utils.h>
#include "i18n.h"
char FileSource::bwf_serial_number[13] = "000000000000";
string FileSource::search_path;
+#undef WE_ARE_BIGENDIAN
+#ifdef __BIG_ENDIAN__
+#define WE_ARE_BIGENDIAN true
+#else
+#define WE_ARE_BIGENDIAN false
+#endif
+
+#define Swap_32(value) \
+ (((((uint32_t)value)<<24) & 0xFF000000) | \
+ ((((uint32_t)value)<< 8) & 0x00FF0000) | \
+ ((((uint32_t)value)>> 8) & 0x0000FF00) | \
+ ((((uint32_t)value)>>24) & 0x000000FF))
+
+#define Swap_16(value) \
+ (((((uint16_t)value)>> 8) & 0x000000FF) | \
+ ((((uint16_t)value)<< 8) & 0x0000FF00))
+
+
void
FileSource::set_search_path (string p)
{
search_path = p;
}
-FileSource::FileSource (string pathstr, jack_nframes_t rate, bool repair_first)
+FileSource::FileSource (string pathstr, jack_nframes_t rate, bool repair_first, SampleFormat samp_format)
{
/* constructor used when the file cannot already exist or might be damaged */
-
+ _sample_format = samp_format;
+ if (samp_format == FormatInt24) {
+ _sample_size = 3;
+ } else {
+ _sample_size = sizeof(float);
+ }
+
if (repair_first && repair (pathstr, rate)) {
throw failed_constructor ();
}
FileSource::FileSource (const XMLNode& node, jack_nframes_t rate)
: Source (node)
{
+ _sample_format = FormatFloat;
+ _sample_size = sizeof(float);
+
if (set_state (node)) {
throw failed_constructor();
}
vector<string*>* result = scanner (search_path, regexp, false, true, -1);
if (result == 0 || result->size() == 0) {
- error << compose (_("FileSource: \"%1\" not found when searching %2 using %3"),
+ error << string_compose (_("FileSource: \"%1\" not found when searching %2 using %3"),
pathstr, search_path, regexp) << endmsg;
goto out;
}
if (result->size() > 1) {
- string msg = compose (_("FileSource: \"%1\" is ambigous when searching %2\n\t"), pathstr, search_path);
+ string msg = string_compose (_("FileSource: \"%1\" is ambigous when searching %2\n\t"), pathstr, search_path);
vector<string*>::iterator x = result->begin();
while (true) {
if (access (_path.c_str(), F_OK) != 0) {
if (must_exist) {
- error << compose(_("Filesource: cannot find required file (%1): %2"), _path, strerror (errno)) << endmsg;
+ error << string_compose(_("Filesource: cannot find required file (%1): %2"), _path, strerror (errno)) << endmsg;
goto out;
}
if (errno == ENOENT) {
new_file = true;
} else {
- error << compose(_("Filesource: cannot check for existing file (%1): %2"), _path, strerror (errno)) << endmsg;
+ error << string_compose(_("Filesource: cannot check for existing file (%1): %2"), _path, strerror (errno)) << endmsg;
goto out;
}
}
if ((fd = open64 (_path.c_str(), O_RDWR|O_CREAT, 0644)) < 0) {
- error << compose(_("FileSource: could not open \"%1\": (%2)"), _path, strerror (errno)) << endmsg;
+ error << string_compose(_("FileSource: could not open \"%1\": (%2)"), _path, strerror (errno)) << endmsg;
goto out;
}
is_bwf = Config->get_native_format_is_bwf ();
if (fill_header (rate)) {
- error << compose (_("FileSource: cannot write header in %1"), _path) << endmsg;
+ error << string_compose (_("FileSource: cannot write header in %1"), _path) << endmsg;
goto out;
}
} else {
if (discover_chunks (must_exist)) {
- error << compose (_("FileSource: cannot locate chunks in %1"), _path) << endmsg;
+ error << string_compose (_("FileSource: cannot locate chunks in %1"), _path) << endmsg;
goto out;
}
if (read_header (must_exist)) {
- error << compose (_("FileSource: cannot read header in %1"), _path) << endmsg;
+ error << string_compose (_("FileSource: cannot read header in %1"), _path) << endmsg;
goto out;
}
if (check_header (rate, must_exist)) {
- error << compose (_("FileSource: cannot check header in %1"), _path) << endmsg;
+ error << string_compose (_("FileSource: cannot check header in %1"), _path) << endmsg;
goto out;
}
}
if ((ret = initialize_peakfile (new_file, _path))) {
- error << compose (_("FileSource: cannot initialize peakfile for %1"), _path) << endmsg;
+ error << string_compose (_("FileSource: cannot initialize peakfile for %1"), _path) << endmsg;
}
out:
off64_t end;
off64_t offset;
char null_terminated_id[5];
-
+ bool doswap = false;
+
if ((end = lseek (fd, 0, SEEK_END)) < 0) {
error << _("FileSource: cannot seek to end of file") << endmsg;
return -1;
return -1;
}
- if (memcmp (rw.id, "RIFF", 4) || memcmp (rw.text, "WAVE", 4)) {
+ if (memcmp (rw.id, "RIFF", 4) == 0 && memcmp (rw.text, "WAVE", 4) == 0) {
+ header.bigendian = false;
+ }
+ else if (memcmp(rw.id, "RIFX", 4) == 0 && memcmp (rw.text, "WAVE", 4) == 0) {
+ header.bigendian = true;
+ }
+ else {
if (!silent) {
- error << compose (_("FileSource %1: not a RIFF/WAVE file"), _path) << endmsg;
+ error << string_compose (_("FileSource %1: not a RIFF/WAVE file"), _path) << endmsg;
}
return -1;
}
/* OK, its a RIFF/WAVE file. Find each chunk */
+ doswap = header.bigendian != WE_ARE_BIGENDIAN;
+
+ if (doswap) {
+ swap_endian(rw);
+ }
+
+
+
memcpy (null_terminated_id, rw.id, 4);
chunk_info.push_back (ChunkInfo (null_terminated_id, rw.size, 0));
return -1;
}
+ if (doswap) {
+ swap_endian(this_chunk);
+ }
+
memcpy (null_terminated_id, this_chunk.id, 4);
+
+ /* do sanity check and possible correction to legacy ardour RIFF wavs
+ created on big endian platforms. after swapping, the size field will not be
+ in range for the fmt chunk
+ */
+ if ((memcmp(null_terminated_id, "fmt ", 4) == 0 || memcmp(null_terminated_id, "bext", 4) == 0)
+ && !header.bigendian && (this_chunk.size > 700 || this_chunk.size < 0))
+ {
+ warning << _("filesource: correcting mis-written RIFF file to become a RIFX: ") << name() << endmsg;
+
+ memcpy (&rw.id, "RIFX", 4);
+ ::pwrite64 (fd, &rw.id, 4, 0);
+ header.bigendian = true;
+ // fix wave chunk already read
+ swap_endian(rw);
+
+ doswap = header.bigendian != WE_ARE_BIGENDIAN;
+
+ // now reset offset and continue the loop
+ // to reread all the chunks
+ chunk_info.clear();
+ memcpy (null_terminated_id, rw.id, 4);
+ chunk_info.push_back (ChunkInfo (null_terminated_id, rw.size, 0));
+ offset = sizeof (rw);
+ continue;
+ }
+
+
if (end != 44)
if ((memcmp(null_terminated_id, "data", 4) == 0))
if ((this_chunk.size == 0) || (this_chunk.size > (end - offset)))
return 0;
}
+void
+FileSource::swap_endian (GenericChunk & chunk) const
+{
+ chunk.size = Swap_32(chunk.size);
+}
+
+void
+FileSource::swap_endian (FMTChunk & chunk) const
+{
+ chunk.size = Swap_32(chunk.size);
+
+ chunk.formatTag = Swap_16(chunk.formatTag);
+ chunk.nChannels = Swap_16(chunk.nChannels);
+ chunk.nSamplesPerSec = Swap_32(chunk.nSamplesPerSec);
+ chunk.nAvgBytesPerSec = Swap_32(chunk.nAvgBytesPerSec);
+ chunk.nBlockAlign = Swap_16(chunk.nBlockAlign);
+ chunk.nBitsPerSample = Swap_16(chunk.nBitsPerSample);
+}
+
+void
+FileSource::swap_endian (BroadcastChunk & chunk) const
+{
+ chunk.size = Swap_32(chunk.size);
+
+ chunk.time_reference_low = Swap_32(chunk.time_reference_low);
+ chunk.time_reference_high = Swap_32(chunk.time_reference_high);
+ chunk.version = Swap_16(chunk.version);
+}
+
+void FileSource::swap_endian (Sample *buf, jack_nframes_t cnt) const
+{
+ for (jack_nframes_t n=0; n < cnt; ++n) {
+ uint32_t * tmp = (uint32_t *) &buf[n];
+ *tmp = Swap_32(*tmp);
+ }
+}
+
+
FileSource::ChunkInfo*
FileSource::lookup_chunk (string what)
{
FileSource::fill_header (jack_nframes_t rate)
{
/* RIFF/WAVE */
-
- memcpy (header.wave.id, "RIFF", 4);
+
+ if (WE_ARE_BIGENDIAN) {
+ memcpy (header.wave.id, "RIFX", 4);
+ header.bigendian = true;
+ }
+ else {
+ memcpy (header.wave.id, "RIFF", 4);
+ header.bigendian = false;
+ }
header.wave.size = 0; /* file size */
memcpy (header.wave.text, "WAVE", 4);
struct utsname utsinfo;
if ((pwinfo = getpwuid (getuid())) == 0) {
- error << compose(_("FileSource: cannot get user information for BWF header (%1)"), strerror(errno)) << endmsg;
+ error << string_compose(_("FileSource: cannot get user information for BWF header (%1)"), strerror(errno)) << endmsg;
return -1;
}
if (uname (&utsinfo)) {
- error << compose(_("FileSource: cannot get host information for BWF header (%1)"), strerror(errno)) << endmsg;
+ error << string_compose(_("FileSource: cannot get host information for BWF header (%1)"), strerror(errno)) << endmsg;
return -1;
}
memcpy (header.format.id, "fmt ", 4);
header.format.size = sizeof (FMTChunk) - sizeof (GenericChunk);
- header.format.formatTag = 3; /* little-endian IEEE float format */
+ if (_sample_format == FormatInt24) {
+ header.format.formatTag = 1; // PCM
+ header.format.nBlockAlign = 3;
+ header.format.nBitsPerSample = 24;
+ }
+ else {
+ header.format.formatTag = 3; /* little-endian IEEE float format */
+ header.format.nBlockAlign = 4;
+ header.format.nBitsPerSample = 32;
+ }
header.format.nChannels = 1; /* mono */
header.format.nSamplesPerSec = rate;
header.format.nAvgBytesPerSec = rate * sizeof (Sample);
- header.format.nBlockAlign = 4;
- header.format.nBitsPerSample = 32;
/* DATA */
compute_header_size ();
if (write_header()) {
- error << compose(_("FileSource[%1]: cannot update data size: %2"), _path, strerror (errno)) << endmsg;
+ error << string_compose(_("FileSource[%1]: cannot update data size: %2"), _path, strerror (errno)) << endmsg;
return -1;
}
/* we already have the chunk info, so just load up whatever we have */
ChunkInfo* info;
-
- if ((info = lookup_chunk ("RIFF")) == 0) {
+
+ if (header.bigendian == false && (info = lookup_chunk ("RIFF")) == 0) {
error << _("FileSource: can't find RIFF chunk info") << endmsg;
return -1;
}
-
+ else if (header.bigendian == true && (info = lookup_chunk ("RIFX")) == 0) {
+ error << _("FileSource: can't find RIFX chunk info") << endmsg;
+ return -1;
+ }
+
+
/* just fill this chunk/header ourselves, disk i/o is stupid */
- memcpy (header.wave.id, "RIFF", 4);
+ if (header.bigendian) {
+ memcpy (header.wave.id, "RIFX", 4);
+ }
+ else {
+ memcpy (header.wave.id, "RIFF", 4);
+ }
header.wave.size = 0;
memcpy (header.wave.text, "WAVE", 4);
return -1;
}
+ if (header.bigendian != WE_ARE_BIGENDIAN) {
+ swap_endian (header.format);
+ }
+
if ((info = lookup_chunk ("data")) == 0) {
error << _("FileSource: can't find data chunk info") << endmsg;
return -1;
return -1;
}
+ if (header.bigendian != WE_ARE_BIGENDIAN) {
+ swap_endian (header.data);
+ }
+
return 0;
}
int32_t coding_history_size;
if (::pread (fd, (char *) &header.bext, sizeof (header.bext), info.offset + sizeof (GenericChunk)) != sizeof (header.bext)) {
- error << compose(_("FileSource: cannot read Broadcast Wave data from existing audio file \"%1\" (%2)"),
+ error << string_compose(_("FileSource: cannot read Broadcast Wave data from existing audio file \"%1\" (%2)"),
_path, strerror (errno)) << endmsg;
return -1;
}
+ if (header.bigendian != WE_ARE_BIGENDIAN) {
+ swap_endian (header.bext);
+ }
+
if (info.size > sizeof (header.bext)) {
coding_history_size = info.size - (sizeof (header.bext) - sizeof (GenericChunk));
char data[coding_history_size];
if (::pread (fd, data, coding_history_size, info.offset + sizeof (BroadcastChunk)) != coding_history_size) {
- error << compose(_("FileSource: cannot read Broadcast Wave coding history from audio file \"%1\" (%2)"),
+ error << string_compose(_("FileSource: cannot read Broadcast Wave coding history from audio file \"%1\" (%2)"),
_path, strerror (errno)) << endmsg;
return -1;
}
int
FileSource::check_header (jack_nframes_t rate, bool silent)
{
- if (header.format.formatTag != 3) { /* IEEE float */
+ if (header.format.formatTag == 1 && header.format.nBitsPerSample == 24) {
+ // 24 bit PCM
+ _sample_format = FormatInt24;
+ _sample_size = 3;
+ } else if (header.format.formatTag == 3) {
+ /* IEEE float */
+ _sample_format = FormatFloat;
+ _sample_size = 4;
+ }
+ else {
if (!silent) {
- error << compose(_("FileSource \"%1\" does not use floating point format.\n"
+ error << string_compose(_("FileSource \"%1\" does not use valid sample format.\n"
"This is probably a programming error."), _path) << endmsg;
}
return -1;
}
if (data_offset == 0) {
- error << compose(_("FileSource \"%1\" has no \"data\" chunk"), _path) << endmsg;
+ error << string_compose(_("FileSource \"%1\" has no \"data\" chunk"), _path) << endmsg;
return -1;
}
if (_length * sizeof (Sample) != (jack_nframes_t) header.data.size) {
- warning << compose(_("%1: data length in header (%2) differs from implicit size in file (%3)"),
+ warning << string_compose(_("%1: data length in header (%2) differs from implicit size in file (%3)"),
_path, header.data.size, _length * sizeof (Sample)) << endmsg;
}
if ((jack_nframes_t) header.format.nSamplesPerSec != rate) {
- warning << compose(_("\"%1\" has a sample rate of %2 instead of %3 as used by this session"),
+ warning << string_compose(_("\"%1\" has a sample rate of %2 instead of %3 as used by this session"),
_path, header.format.nSamplesPerSec, rate) << endmsg;
}
/* write RIFF/WAVE boilerplate */
pos = 0;
+
+ WAVEChunk wchunk = header.wave;
+
+ if (header.bigendian != WE_ARE_BIGENDIAN) {
+ swap_endian(wchunk);
+ }
- if (::pwrite64 (fd, (char *) &header.wave, sizeof (header.wave), pos) != sizeof (header.wave)) {
- error << compose(_("FileSource: cannot write WAVE chunk: %1"), strerror (errno)) << endmsg;
+ if (::pwrite64 (fd, (char *) &wchunk, sizeof (wchunk), pos) != sizeof (wchunk)) {
+ error << string_compose(_("FileSource: cannot write WAVE chunk: %1"), strerror (errno)) << endmsg;
return -1;
}
/* write broadcast chunk data without copy history */
- if (::pwrite64 (fd, (char *) &header.bext, sizeof (header.bext), pos) != sizeof (header.bext)) {
+ BroadcastChunk bchunk = header.bext;
+ if (header.bigendian != WE_ARE_BIGENDIAN) {
+ swap_endian (bchunk);
+ }
+
+ if (::pwrite64 (fd, (char *) &bchunk, sizeof (bchunk), pos) != sizeof (bchunk)) {
return -1;
}
}
/* write fmt and data chunks */
-
- if (::pwrite64 (fd, (char *) &header.format, sizeof (header.format), pos) != sizeof (header.format)) {
- error << compose(_("FileSource: cannot write format chunk: %1"), strerror (errno)) << endmsg;
+ FMTChunk fchunk = header.format;
+ if (header.bigendian != WE_ARE_BIGENDIAN) {
+ swap_endian (fchunk);
+ }
+
+ if (::pwrite64 (fd, (char *) &fchunk, sizeof (fchunk), pos) != sizeof (fchunk)) {
+ error << string_compose(_("FileSource: cannot write format chunk: %1"), strerror (errno)) << endmsg;
return -1;
}
pos += sizeof (header.format);
-
- if (::pwrite64 (fd, (char *) &header.data, sizeof (header.data), pos) != sizeof (header.data)) {
- error << compose(_("FileSource: cannot data chunk: %1"), strerror (errno)) << endmsg;
+
+ GenericChunk dchunk = header.data;
+ if (header.bigendian != WE_ARE_BIGENDIAN) {
+ swap_endian (dchunk);
+ }
+
+ if (::pwrite64 (fd, (char *) &dchunk, sizeof (dchunk), pos) != sizeof (dchunk)) {
+ error << string_compose(_("FileSource: cannot data chunk: %1"), strerror (errno)) << endmsg;
return -1;
}
}
jack_nframes_t
-FileSource::read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const
+FileSource::read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const
{
LockMonitor lm (_lock, __LINE__, __FILE__);
- return read_unlocked (dst, start, cnt);
+ return read_unlocked (dst, start, cnt, workbuf);
}
jack_nframes_t
-FileSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const
+FileSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const
{
- int32_t byte_cnt;
- int nread;
-
- byte_cnt = cnt * sizeof (Sample);
-
- if ((nread = pread (fd, (char *) dst, byte_cnt, data_offset + (start * sizeof (Sample)))) != (off64_t) byte_cnt) {
-
- cerr << "FileSource: \""
- << _path
- << "\" bad read at frame "
- << start
- << ", of "
- << cnt
- << " (bytes="
- << byte_cnt
- << ") frames [length = " << _length
- << " eor = " << start + cnt << "] ("
- << strerror (errno)
- << ") (read "
- << nread / sizeof (Sample)
- << " (bytes=" <<nread
- << ")) pos was"
- << data_offset
- << '+'
- << start << '*' << sizeof(Sample)
- << " = " << data_offset + (start * sizeof(Sample))
- << endl;
-
+
+ if (file_read(dst, start, cnt, workbuf) != (ssize_t) cnt) {
return 0;
}
-
- _read_data_count = byte_cnt;
-
+
return cnt;
}
jack_nframes_t
-FileSource::write (Sample *data, jack_nframes_t cnt)
+FileSource::write (Sample *data, jack_nframes_t cnt, char * workbuf)
{
{
LockMonitor lm (_lock, __LINE__, __FILE__);
- int32_t byte_cnt = cnt * sizeof (Sample);
- int32_t byte_pos = data_offset + (_length * sizeof (Sample));
jack_nframes_t oldlen;
-
- if (::pwrite64 (fd, (char *) data, byte_cnt, byte_pos) != (off64_t) byte_cnt) {
- error << compose(_("FileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
+ int32_t frame_pos = _length;
+
+ if (file_write(data, frame_pos, cnt, workbuf) != (ssize_t) cnt) {
return 0;
}
oldlen = _length;
_length += cnt;
- _write_data_count = byte_cnt;
if (_build_peakfiles) {
PeakBuildRecord *pbr = 0;
return cnt;
}
+ssize_t
+FileSource::write_float(Sample *data, jack_nframes_t framepos, jack_nframes_t cnt, char * workbuf)
+{
+ int32_t byte_cnt = cnt * _sample_size;
+ int32_t byte_pos = data_offset + (framepos * _sample_size);
+ ssize_t retval;
+
+ if ((retval = ::pwrite64 (fd, (char *) data, byte_cnt, byte_pos)) != (ssize_t) byte_cnt) {
+ error << string_compose(_("FileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
+ if (retval > 0) {
+ return retval / _sample_size;
+ }
+ else {
+ return retval;
+ }
+ }
+
+ _write_data_count = byte_cnt;
+
+ return cnt;
+}
+
+ssize_t
+FileSource::read_float (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const
+{
+ ssize_t nread;
+ ssize_t byte_cnt = (ssize_t) cnt * sizeof (Sample);
+
+ if ((nread = pread (fd, (char *) dst, byte_cnt, data_offset + (start * _sample_size))) != byte_cnt) {
+
+ cerr << "FileSource: \""
+ << _path
+ << "\" bad read at frame "
+ << start
+ << ", of "
+ << cnt
+ << " (bytes="
+ << byte_cnt
+ << ") frames [length = " << _length
+ << " eor = " << start + cnt << "] ("
+ << strerror (errno)
+ << ") (read "
+ << nread / sizeof (Sample)
+ << " (bytes=" <<nread
+ << ")) pos was"
+ << data_offset
+ << '+'
+ << start << '*' << sizeof(Sample)
+ << " = " << data_offset + (start * sizeof(Sample))
+ << endl;
+
+ if (nread > 0) {
+ return nread / _sample_size;
+ }
+ else {
+ return nread;
+ }
+ }
+
+ if (header.bigendian != WE_ARE_BIGENDIAN) {
+ swap_endian(dst, cnt);
+ }
+
+ _read_data_count = byte_cnt;
+
+ return cnt;
+}
+
+ssize_t
+FileSource::write_pcm_24(Sample *data, jack_nframes_t framepos, jack_nframes_t cnt, char * workbuf)
+{
+ int32_t byte_cnt = cnt * _sample_size;
+ int32_t byte_pos = data_offset + (framepos * _sample_size);
+ ssize_t retval;
+
+ // convert to int24
+ if (header.bigendian) {
+ pcm_f2bet_clip_array (data, workbuf, cnt);
+ } else {
+ pcm_f2let_clip_array (data, workbuf, cnt);
+ }
+
+ if ((retval = ::pwrite64 (fd, (char *) workbuf, byte_cnt, byte_pos)) != (ssize_t) byte_cnt) {
+ error << string_compose(_("FileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
+ if (retval > 0) {
+ return retval / _sample_size;
+ }
+ else {
+ return retval;
+ }
+ }
+
+ return (ssize_t) cnt;
+}
+
+ssize_t
+FileSource::read_pcm_24 (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const
+{
+ ssize_t nread;
+ ssize_t byte_cnt = (ssize_t) cnt * _sample_size;
+
+ if ((nread = pread (fd, (char *) workbuf, byte_cnt, data_offset + (start * _sample_size))) != byte_cnt) {
+
+ cerr << "FileSource: \""
+ << _path
+ << "\" bad 24bit read at frame "
+ << start
+ << ", of "
+ << cnt
+ << " (bytes="
+ << byte_cnt
+ << ") frames [length = " << _length
+ << " eor = " << start + cnt << "] ("
+ << strerror (errno)
+ << ") (read "
+ << nread / sizeof (Sample)
+ << " (bytes=" <<nread
+ << ")) pos was"
+ << data_offset
+ << '+'
+ << start << '*' << sizeof(Sample)
+ << " = " << data_offset + (start * sizeof(Sample))
+ << endl;
+
+ if (nread > 0) {
+ return nread / _sample_size;
+ }
+ else {
+ return nread;
+ }
+ }
+
+ // convert from 24bit->float
+
+ if (header.bigendian) {
+ pcm_bet2f_array (workbuf, cnt, dst);
+ } else {
+ pcm_let2f_array (workbuf, cnt, dst);
+ }
+
+ _read_data_count = byte_cnt;
+
+ return (ssize_t) cnt;
+}
+
+
bool
FileSource::is_empty (string path)
{
}
if (version == 999) {
- error << compose (_("there are already 1000 files with names like %1; versioning discontinued"),
+ error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
newpath)
<< endmsg;
} else {
}
if (::rename (_path.c_str(), newpath.c_str()) != 0) {
- error << compose (_("cannot rename audio file source from %1 to %2 (%3)"),
+ error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
_path, newpath, strerror (errno))
<< endmsg;
return -1;
}
if (::unlink (peakpath.c_str()) != 0) {
- error << compose (_("cannot remove peakfile %1 for %2 (%3)"),
+ error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
peakpath, _path, strerror (errno))
<< endmsg;
/* try to back out */
struct stat statbuf;
size_t i;
int ret = -1;
-
+ bool bigend = false;
+ bool doswap = false;
+
if (stat (path.c_str(), &statbuf)) {
return -1;
}
goto out;
}
- if (memcmp (&buf[0], "RIFF", 4) || memcmp (&buf[8], "WAVE", 4)) {
+ if (memcmp (&buf[0], "RIFF", 4) || memcmp (&buf[8], "WAVE", 4) || memcmp (&buf[0], "RIFX", 4)) {
/* no header. too dangerous to proceed */
goto out;
-
}
+ if (memcmp (&buf[0], "RIFX", 4)==0) {
+ bigend = true;
+ }
+
+ doswap = bigend != WE_ARE_BIGENDIAN;
+
/* reset the size of the RIFF chunk header */
- *((int32_t *)&buf[4]) = statbuf.st_size - 8;
+ if (doswap) {
+ *((int32_t *)&buf[4]) = Swap_32((int32_t)(statbuf.st_size - 8));
+ }
+ else {
+ *((int32_t *)&buf[4]) = statbuf.st_size - 8;
+ }
/* find data chunk and reset the size */
FMTChunk fmt;
memcpy (&fmt, ptr, sizeof (fmt));
+ if (doswap) {
+ swap_endian(fmt);
+ }
+
fmt.nSamplesPerSec = rate;
fmt.nAvgBytesPerSec = rate * 4;
/* put it back */
+ if (doswap) {
+ swap_endian(fmt);
+ }
memcpy (ptr, &fmt, sizeof (fmt));
ptr += sizeof (fmt);
i += sizeof (fmt);
} else if (memcmp (ptr, "data", 4) == 0) {
+ GenericChunk dchunk;
+ memcpy(&dchunk, ptr, sizeof(dchunk));
+
+ if(doswap) {
+ swap_endian(dchunk);
+ }
+
+ dchunk.size = statbuf.st_size - i - 8;
- *((int32_t *)&ptr[4]) = statbuf.st_size - i - 8;
+ if (doswap) {
+ swap_endian(dchunk);
+ }
+ memcpy (ptr, &dchunk, sizeof (dchunk));
break;
} else {