summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Chappell <jesse@essej.net>2005-11-29 06:49:00 +0000
committerJesse Chappell <jesse@essej.net>2005-11-29 06:49:00 +0000
commitd9b463178f20a236c7ff23180f94e76435f2e98a (patch)
tree52c8695b8a6d0e845df61a38e80f62e6521b1229
parentb1a99f89da52018d3995592eb821f8e4a3c89a28 (diff)
committed fix for cross-endian native wave files
git-svn-id: svn://localhost/trunk/ardour2@146 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--SConstruct8
-rw-r--r--libs/ardour/SConscript5
-rw-r--r--libs/ardour/ardour/filesource.h6
-rw-r--r--libs/ardour/filesource.cc224
-rw-r--r--libs/ardour/panner.cc11
-rw-r--r--libs/ardour/source.cc2
6 files changed, 232 insertions, 24 deletions
diff --git a/SConstruct b/SConstruct
index 98d422cd8d..c3a46812e3 100644
--- a/SConstruct
+++ b/SConstruct
@@ -651,6 +651,14 @@ if env['VST']:
env.Append(CCFLAGS="-DVST_SUPPORT")
+# check endianness
+if sys.byteorder == "big":
+ print "Host is big endian"
+ env.Append(CCFLAGS="-DWORDS_BIGENDIAN")
+else:
+ print "Host is little endian"
+
+
#
# everybody needs this
#
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript
index 40e505e0f3..a063d4b86b 100644
--- a/libs/ardour/SConscript
+++ b/libs/ardour/SConscript
@@ -140,8 +140,9 @@ conf = Configure(ardour, custom_tests = {
'CheckJackRecomputeLatencies' : CheckJackRecomputeLatencies
})
-if conf.CheckJackClientOpen():
- ardour.Append(CXXFLAGS="-DHAVE_JACK_CLIENT_OPEN")
+#if conf.CheckJackClientOpen():
+# HACK BY JLC, not to be committed!
+ardour.Append(CXXFLAGS="-DHAVE_JACK_CLIENT_OPEN")
if conf.CheckJackRecomputeLatencies():
ardour.Append(CXXFLAGS="-DHAVE_JACK_RECOMPUTE_LATENCIES")
diff --git a/libs/ardour/ardour/filesource.h b/libs/ardour/ardour/filesource.h
index 2c24d87793..75f454f554 100644
--- a/libs/ardour/ardour/filesource.h
+++ b/libs/ardour/ardour/filesource.h
@@ -133,6 +133,7 @@ class FileSource : public Source {
GenericChunk data;
BroadcastChunk bext;
vector<string> coding_history;
+ bool bigendian;
} header;
int init (string, bool must_exist, jack_nframes_t);
@@ -156,6 +157,11 @@ class FileSource : public Source {
static string search_path;
int repair (string, jack_nframes_t);
+
+ void swap_endian (GenericChunk & chunk) const;
+ void swap_endian (FMTChunk & chunk) const;
+ void swap_endian (BroadcastChunk & chunk) const;
+ void swap_endian (Sample *buf, jack_nframes_t cnt) const;
};
}
diff --git a/libs/ardour/filesource.cc b/libs/ardour/filesource.cc
index f7ecdc1136..fd74f66e76 100644
--- a/libs/ardour/filesource.cc
+++ b/libs/ardour/filesource.cc
@@ -77,6 +77,24 @@ char FileSource::bwf_organization_code[4] = "las";
char FileSource::bwf_serial_number[13] = "000000000000";
string FileSource::search_path;
+#undef WE_ARE_BIGENDIAN
+#ifdef WORDS_BIGENDIAN
+#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)
{
@@ -313,7 +331,8 @@ FileSource::discover_chunks (bool silent)
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;
@@ -324,7 +343,13 @@ FileSource::discover_chunks (bool silent)
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 << string_compose (_("FileSource %1: not a RIFF/WAVE file"), _path) << endmsg;
}
@@ -335,6 +360,14 @@ FileSource::discover_chunks (bool silent)
/* 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));
@@ -349,7 +382,39 @@ FileSource::discover_chunks (bool silent)
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)))
@@ -365,6 +430,44 @@ FileSource::discover_chunks (bool silent)
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)
{
@@ -380,8 +483,15 @@ int
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);
@@ -558,15 +668,25 @@ FileSource::read_header (bool silent)
/* 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);
@@ -594,6 +714,10 @@ FileSource::read_header (bool silent)
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;
@@ -604,6 +728,10 @@ FileSource::read_header (bool silent)
return -1;
}
+ if (header.bigendian != WE_ARE_BIGENDIAN) {
+ swap_endian (header.data);
+ }
+
return 0;
}
@@ -618,6 +746,10 @@ FileSource::read_broadcast_data (ChunkInfo& info)
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));
@@ -722,8 +854,14 @@ FileSource::write_header()
/* 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)) {
+ if (::pwrite64 (fd, (char *) &wchunk, sizeof (wchunk), pos) != sizeof (wchunk)) {
error << string_compose(_("FileSource: cannot write WAVE chunk: %1"), strerror (errno)) << endmsg;
return -1;
}
@@ -734,7 +872,12 @@ FileSource::write_header()
/* 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;
}
@@ -757,15 +900,24 @@ FileSource::write_header()
}
/* write fmt and data chunks */
-
- if (::pwrite64 (fd, (char *) &header.format, sizeof (header.format), pos) != sizeof (header.format)) {
+ 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)) {
+
+ 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;
}
@@ -820,6 +972,10 @@ FileSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt
return 0;
}
+ if (header.bigendian != WE_ARE_BIGENDIAN) {
+ swap_endian(dst, cnt);
+ }
+
_read_data_count = byte_cnt;
return cnt;
@@ -1023,7 +1179,9 @@ FileSource::repair (string path, jack_nframes_t rate)
struct stat statbuf;
size_t i;
int ret = -1;
-
+ bool bigend = false;
+ bool doswap = false;
+
if (stat (path.c_str(), &statbuf)) {
return -1;
}
@@ -1043,15 +1201,25 @@ FileSource::repair (string path, jack_nframes_t rate)
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 */
@@ -1064,18 +1232,36 @@ FileSource::repair (string path, jack_nframes_t rate)
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);
+ }
- *((int32_t *)&ptr[4]) = statbuf.st_size - i - 8;
+ dchunk.size = statbuf.st_size - i - 8;
+
+ if (doswap) {
+ swap_endian(dchunk);
+ }
+ memcpy (ptr, &dchunk, sizeof (dchunk));
break;
} else {
diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc
index 63bcd7f302..130db16191 100644
--- a/libs/ardour/panner.cc
+++ b/libs/ardour/panner.cc
@@ -41,6 +41,9 @@
#include "i18n.h"
+#include <pbd/mathfix.h>
+
+
using namespace std;
using namespace ARDOUR;
@@ -778,8 +781,12 @@ Multi2dPanner::update ()
}
f += dsq[i] * dsq[i];
}
- fr = 1.0f / sqrtf(f);
-
+#ifdef __APPLE__
+ // terrible hack to support OSX < 10.3.9 builds
+ fr = (float) (1.0 / sqrt((double)f));
+#else
+ fr = 1.0 / sqrtf(f);
+#endif
for (i = 0; i < nouts; ++i) {
parent.outputs[i].desired_pan = 1.0f - (dsq[i] * fr);
}
diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc
index 12b3f08267..515e8d4e9b 100644
--- a/libs/ardour/source.cc
+++ b/libs/ardour/source.cc
@@ -791,7 +791,7 @@ Source::do_build_peak (jack_nframes_t first_frame, jack_nframes_t cnt)
cnt -= frames_read;
}
- if (::pwrite (peakfile, peakbuf, sizeof (PeakData) * peaki, first_peak_byte) != (ssize_t) sizeof (PeakData) * peaki) {
+ if (::pwrite (peakfile, peakbuf, sizeof (PeakData) * peaki, first_peak_byte) != (ssize_t) (sizeof (PeakData) * peaki)) {
error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
goto out;
}