diff options
author | Jesse Chappell <jesse@essej.net> | 2006-02-10 23:53:12 +0000 |
---|---|---|
committer | Jesse Chappell <jesse@essej.net> | 2006-02-10 23:53:12 +0000 |
commit | 9ab70fb55284537228577d575f15aa03949bd678 (patch) | |
tree | 47a44c65846a46bb6bff1b49caa8edb68c2b8c13 /libs | |
parent | 17cb448b1df0def4c1e09da615e11a64f6e692e3 (diff) |
committed INCOMPLETE 24bit filesource support
git-svn-id: svn://localhost/trunk/ardour2@316 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
33 files changed, 617 insertions, 172 deletions
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript index b1cab4bb7d..5f51e839eb 100644 --- a/libs/ardour/SConscript +++ b/libs/ardour/SConscript @@ -50,6 +50,7 @@ location.cc mtc_slave.cc named_selection.cc panner.cc +pcm_utils.cc playlist.cc playlist_factory.cc plugin.cc diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h index 030dd17a6b..0ef4c45f16 100644 --- a/libs/ardour/ardour/audio_track.h +++ b/libs/ardour/ardour/audio_track.h @@ -63,7 +63,7 @@ class AudioTrack : public Route jack_nframes_t update_total_latency(); void set_latency_delay (jack_nframes_t); - int export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t end_frame); + int export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t end_frame); sigc::signal<void,void*> diskstream_changed; diff --git a/libs/ardour/ardour/audioplaylist.h b/libs/ardour/ardour/audioplaylist.h index 26cce91b12..fa2aa94471 100644 --- a/libs/ardour/ardour/audioplaylist.h +++ b/libs/ardour/ardour/audioplaylist.h @@ -60,7 +60,7 @@ class AudioPlaylist : public ARDOUR::Playlist void clear (bool with_delete = false, bool with_save = true); - jack_nframes_t read (Sample *dst, Sample *mixdown, float *gain_buffer, jack_nframes_t start, jack_nframes_t cnt, uint32_t chan_n=0); + jack_nframes_t read (Sample *dst, Sample *mixdown, float *gain_buffer, char * workbuf, jack_nframes_t start, jack_nframes_t cnt, uint32_t chan_n=0); int set_state (const XMLNode&); UndoAction get_memento() const; diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index 44159f73f5..fa6b3aeecc 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -104,13 +104,13 @@ class AudioRegion : public Region jack_nframes_t read_peaks (PeakData *buf, jack_nframes_t npeaks, jack_nframes_t offset, jack_nframes_t cnt, uint32_t chan_n=0, double samples_per_unit= 1.0) const; virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buffer, - float *gain_buffer, jack_nframes_t position, jack_nframes_t cnt, + float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n = 0, jack_nframes_t read_frames = 0, jack_nframes_t skip_frames = 0) const; jack_nframes_t master_read_at (Sample *buf, Sample *mixdown_buffer, - float *gain_buffer, jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n=0) const; + float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n=0) const; XMLNode& state (bool); @@ -199,7 +199,7 @@ class AudioRegion : public Region void rename_after_first_edit (); jack_nframes_t _read_at (const SourceList&, Sample *buf, Sample *mixdown_buffer, - float *gain_buffer, jack_nframes_t position, jack_nframes_t cnt, + float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n = 0, jack_nframes_t read_frames = 0, jack_nframes_t skip_frames = 0) const; diff --git a/libs/ardour/ardour/crossfade.h b/libs/ardour/ardour/crossfade.h index 4db833ca45..3e65e16901 100644 --- a/libs/ardour/ardour/crossfade.h +++ b/libs/ardour/ardour/crossfade.h @@ -87,7 +87,7 @@ class Crossfade : public Stateful, public StateManager ARDOUR::AudioRegion& out() const { return *_out; } jack_nframes_t read_at (Sample *buf, Sample *mixdown_buffer, - float *gain_buffer, jack_nframes_t position, jack_nframes_t cnt, + float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n, jack_nframes_t read_frames = 0, jack_nframes_t skip_frames = 0); diff --git a/libs/ardour/ardour/destructive_filesource.h b/libs/ardour/ardour/destructive_filesource.h index bb46fdfd22..ceb049b29c 100644 --- a/libs/ardour/ardour/destructive_filesource.h +++ b/libs/ardour/ardour/destructive_filesource.h @@ -31,7 +31,7 @@ namespace ARDOUR { class DestructiveFileSource : public FileSource { public: - DestructiveFileSource (std::string path, jack_nframes_t rate, bool repair_first = false); + DestructiveFileSource (std::string path, jack_nframes_t rate, bool repair_first = false, SampleFormat samp_format=FormatInt24); DestructiveFileSource (const XMLNode&, jack_nframes_t rate); ~DestructiveFileSource (); @@ -41,7 +41,7 @@ class DestructiveFileSource : public FileSource { void mark_capture_end (); void clear_capture_marks(); - jack_nframes_t write (Sample *src, jack_nframes_t cnt); + jack_nframes_t write (Sample *src, jack_nframes_t cnt, char * workbuf); private: static jack_nframes_t xfade_frames; @@ -52,10 +52,10 @@ class DestructiveFileSource : public FileSource { bool _capture_start; bool _capture_end; jack_nframes_t capture_start_frame; - jack_nframes_t file_pos; + jack_nframes_t file_pos; // unit is frames Sample* xfade_buf; - jack_nframes_t crossfade (Sample* data, jack_nframes_t cnt, int dir); + jack_nframes_t crossfade (Sample* data, jack_nframes_t cnt, int dir, char * workbuf); }; diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h index 5b63cfad28..1d06c4ee49 100644 --- a/libs/ardour/ardour/diskstream.h +++ b/libs/ardour/ardour/diskstream.h @@ -362,10 +362,10 @@ class DiskStream : public Stateful, public sigc::trackable /* the two central butler operations */ - int do_flush (bool force = false); - int do_refill (Sample *mixdown_buffer, float *gain_buffer); + int do_flush (char * workbuf, bool force = false); + int do_refill (Sample *mixdown_buffer, float *gain_buffer, char *workbuf); - int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, jack_nframes_t& start, jack_nframes_t cnt, + int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, char * workbuf, jack_nframes_t& start, jack_nframes_t cnt, ChannelInfo& channel_info, int channel, bool reversed); uint32_t i_am_the_modifier; diff --git a/libs/ardour/ardour/filesource.h b/libs/ardour/ardour/filesource.h index e426159014..af46596ec5 100644 --- a/libs/ardour/ardour/filesource.h +++ b/libs/ardour/ardour/filesource.h @@ -44,13 +44,19 @@ namespace ARDOUR { class FileSource : public Source { public: - FileSource (string path, jack_nframes_t rate, bool repair_first = false); + enum SampleFormat + { + FormatFloat = 0, + FormatInt24 + }; + + FileSource (string path, jack_nframes_t rate, bool repair_first = false, SampleFormat samp_format=FormatFloat); FileSource (const XMLNode&, jack_nframes_t rate); ~FileSource (); jack_nframes_t length() const { return _length; } - jack_nframes_t read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const; - jack_nframes_t write (Sample *src, jack_nframes_t cnt); + jack_nframes_t read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const; + jack_nframes_t write (Sample *src, jack_nframes_t cnt, char * workbuf); void mark_for_remove(); string peak_path(string audio_path); string old_peak_path(string audio_path); @@ -85,7 +91,9 @@ class FileSource : public Source { bool is_bwf; off64_t data_offset; string _take_id; - + SampleFormat _sample_format; + int _sample_size; + static char bwf_country_code[3]; static char bwf_organization_code[4]; static char bwf_serial_number[13]; @@ -143,8 +151,27 @@ class FileSource : public Source { } header; int init (string, bool must_exist, jack_nframes_t); - jack_nframes_t read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const; - + jack_nframes_t read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const; + + ssize_t file_write (Sample *src, jack_nframes_t framepos, jack_nframes_t cnt, char * workbuf) { + switch (_sample_format) { + case FormatInt24: return write_pcm_24(src, framepos, cnt, workbuf); + default: return write_float(src, framepos, cnt, workbuf); + }; + } + + ssize_t file_read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const { + switch (_sample_format) { + case FormatInt24: return read_pcm_24(dst, start, cnt, workbuf); + default: return read_float(dst, start, cnt, workbuf); + }; + } + + ssize_t write_float(Sample *src, jack_nframes_t framepos, jack_nframes_t cnt, char * workbuf); + ssize_t read_float (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const; + ssize_t write_pcm_24(Sample *src, jack_nframes_t framepos, jack_nframes_t cnt, char * workbuf); + ssize_t read_pcm_24 (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const; + int discover_chunks (bool silent); ChunkInfo* lookup_chunk (string name); diff --git a/libs/ardour/ardour/pcm_utils.h b/libs/ardour/ardour/pcm_utils.h new file mode 100644 index 0000000000..6866e53251 --- /dev/null +++ b/libs/ardour/ardour/pcm_utils.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 2006 Paul Davis , portions Erik de Castro Lopo + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_pcm_utils_h__ +#define __ardour_pcm_utils_h__ + +typedef void tribyte ; + +#define SIZEOF_TRIBYTE 3 + +#define BET2H_INT_PTR(x) (((x) [0] << 24) + ((x) [1] << 16) + ((x) [2] << 8)) +#define LET2H_INT_PTR(x) (((x) [0] << 8) + ((x) [1] << 16) + ((x) [2] << 24)) + + + +void pcm_let2f_array (tribyte *src, int count, float *dest); +void pcm_bet2f_array (tribyte *src, int count, float *dest); +void pcm_f2let_array (float *src, tribyte *dest, int count); +void pcm_f2let_clip_array (float *src, tribyte *dest, int count); +void pcm_f2bet_array (const float *src, tribyte *dest, int count); +void pcm_f2bet_clip_array (const float *src, tribyte *dest, int count); + + + +#endif diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index a5451c30d5..b0ac956d5c 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -53,7 +53,7 @@ class Playlist : public Stateful, public StateManager { Playlist (const Playlist&, string name, bool hidden = false); Playlist (const Playlist&, jack_nframes_t start, jack_nframes_t cnt, string name, bool hidden = false); - virtual jack_nframes_t read (Sample *dst, Sample *mixdown, float *gain_buffer, jack_nframes_t start, jack_nframes_t cnt, uint32_t chan_n=0) = 0; + virtual jack_nframes_t read (Sample *dst, Sample *mixdown, float *gain_buffer, char * workbuf, jack_nframes_t start, jack_nframes_t cnt, uint32_t chan_n=0) = 0; virtual void clear (bool with_delete = false, bool with_save = true); virtual void dump () const; virtual UndoAction get_memento() const = 0; diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h index e067f56f44..5af5a660c1 100644 --- a/libs/ardour/ardour/region.h +++ b/libs/ardour/ardour/region.h @@ -141,7 +141,7 @@ class Region : public Stateful, public StateManager } virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buffer, - float *gain_buffer, jack_nframes_t position, jack_nframes_t cnt, + float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n = 0, jack_nframes_t read_frames = 0, jack_nframes_t skip_frames = 0) const = 0; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index a2a62703e4..d4ca8c1ddc 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -923,6 +923,15 @@ class Session : public sigc::trackable, public Stateful gain_t* gain_automation_buffer () const { return _gain_automation_buffer; } pan_t** pan_automation_buffer() const { return _pan_automation_buffer; } + /* buffers for conversion */ + enum RunContext { + ButlerContext = 0, + TransportContext, + ExportContext + }; + + char * conversion_buffer(RunContext context) { return _conversion_buffers[context]; } + /* VST support */ static long vst_callback (AEffect* effect, @@ -998,6 +1007,7 @@ class Session : public sigc::trackable, public Stateful jack_nframes_t last_stop_frame; vector<Sample *> _passthru_buffers; vector<Sample *> _silent_buffers; + map<RunContext,char*> _conversion_buffers; jack_nframes_t current_block_size; jack_nframes_t _worst_output_latency; jack_nframes_t _worst_input_latency; diff --git a/libs/ardour/ardour/sndfilesource.h b/libs/ardour/ardour/sndfilesource.h index 7f9712b7ec..a7583c4fe1 100644 --- a/libs/ardour/ardour/sndfilesource.h +++ b/libs/ardour/ardour/sndfilesource.h @@ -34,7 +34,7 @@ class SndFileSource : public Source { ~SndFileSource (); jack_nframes_t length() const { return _info.frames; } - jack_nframes_t read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const; + jack_nframes_t read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const; void mark_for_remove() {} // we never remove external sndfiles string peak_path(string audio_path); string old_peak_path(string audio_path); @@ -54,7 +54,7 @@ class SndFileSource : public Source { string _path; void init (const string &str, bool build_peak); - jack_nframes_t read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const; + jack_nframes_t read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const; }; }; /* namespace EDL */ diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h index e9afc04f03..9772968288 100644 --- a/libs/ardour/ardour/source.h +++ b/libs/ardour/ardour/source.h @@ -64,11 +64,11 @@ class Source : public Stateful, public sigc::trackable return _length; } - virtual jack_nframes_t read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const { + virtual jack_nframes_t read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const { return 0; } - virtual jack_nframes_t write (Sample *src, jack_nframes_t cnt) { + virtual jack_nframes_t write (Sample *src, jack_nframes_t cnt, char * workbuf) { return 0; } @@ -134,7 +134,7 @@ class Source : public Stateful, public sigc::trackable void build_peaks_from_scratch (); int do_build_peak (jack_nframes_t, jack_nframes_t); - virtual jack_nframes_t read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const = 0; + virtual jack_nframes_t read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const = 0; virtual string peak_path(string audio_path) = 0; virtual string old_peak_path(string audio_path) = 0; diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc index be977447b7..f6c6440ab0 100644 --- a/libs/ardour/audio_playlist.cc +++ b/libs/ardour/audio_playlist.cc @@ -139,7 +139,7 @@ struct RegionSortByLayer { }; jack_nframes_t -AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, jack_nframes_t start, +AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, char * workbuf, jack_nframes_t start, jack_nframes_t cnt, unsigned chan_n) { jack_nframes_t ret = cnt; @@ -209,13 +209,13 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, ja vector<Crossfade*>& x (relevant_xfades[*l]); for (vector<Region*>::iterator i = r.begin(); i != r.end(); ++i) { - (*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n, read_frames, skip_frames); + (*i)->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n, read_frames, skip_frames); _read_data_count += (*i)->read_data_count(); } for (vector<Crossfade*>::iterator i = x.begin(); i != x.end(); ++i) { - (*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n); + (*i)->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n); /* don't JACK up _read_data_count, since its the same data as we just read from the regions, and the OS should handle that for us. diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index dd9648c7bf..7bf8d5732f 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -768,7 +768,7 @@ AudioTrack::set_name (string str, void *src) } int -AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes_t start, jack_nframes_t nframes) +AudioTrack::export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbufs, jack_nframes_t start, jack_nframes_t nframes) { gain_t gain_automation[nframes]; gain_t gain_buffer[nframes]; @@ -781,7 +781,7 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes RWLockMonitor rlock (redirect_lock, false, __LINE__, __FILE__); - if (diskstream->playlist()->read (buffers[0], mix_buffer, gain_buffer, start, nframes) != nframes) { + if (diskstream->playlist()->read (buffers[0], mix_buffer, gain_buffer, workbuf, start, nframes) != nframes) { return -1; } @@ -791,7 +791,7 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes ++bi; for (; bi != buffers.end(); ++bi, ++n) { if (n < diskstream->n_channels()) { - if (diskstream->playlist()->read ((*bi), mix_buffer, gain_buffer, start, nframes, n) != nframes) { + if (diskstream->playlist()->read ((*bi), mix_buffer, gain_buffer, workbuf, start, nframes, n) != nframes) { return -1; } b = (*bi); diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index bc14968fa7..804e378a16 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -462,22 +462,22 @@ AudioRegion::read_peaks (PeakData *buf, jack_nframes_t npeaks, jack_nframes_t of } jack_nframes_t -AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, jack_nframes_t position, +AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n, jack_nframes_t read_frames, jack_nframes_t skip_frames) const { - return _read_at (sources, buf, mixdown_buffer, gain_buffer, position, cnt, chan_n, read_frames, skip_frames); + return _read_at (sources, buf, mixdown_buffer, gain_buffer, workbuf, position, cnt, chan_n, read_frames, skip_frames); } jack_nframes_t -AudioRegion::master_read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, jack_nframes_t position, +AudioRegion::master_read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n) const { - return _read_at (master_sources, buf, mixdown_buffer, gain_buffer, position, cnt, chan_n, 0, 0); + return _read_at (master_sources, buf, mixdown_buffer, gain_buffer, workbuf, position, cnt, chan_n, 0, 0); } jack_nframes_t -AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buffer, float *gain_buffer, +AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buffer, float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n, jack_nframes_t read_frames, jack_nframes_t skip_frames) const { @@ -522,7 +522,7 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff _read_data_count = 0; - if (srcs[chan_n]->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) { + if (srcs[chan_n]->read (mixdown_buffer, _start + internal_offset, to_read, workbuf) != to_read) { return 0; /* "read nothing" */ } @@ -1204,7 +1204,7 @@ AudioRegion::exportme (Session& session, AudioExportSpecification& spec) if (spec.channels == 1) { - if (sources.front()->read (spec.dataF, _start + spec.pos, to_read) != to_read) { + if (sources.front()->read (spec.dataF, _start + spec.pos, to_read, 0) != to_read) { goto out; } @@ -1214,7 +1214,7 @@ AudioRegion::exportme (Session& session, AudioExportSpecification& spec) for (uint32_t chan = 0; chan < spec.channels; ++chan) { - if (sources[chan]->read (buf, _start + spec.pos, to_read) != to_read) { + if (sources[chan]->read (buf, _start + spec.pos, to_read, 0) != to_read) { goto out; } @@ -1276,6 +1276,7 @@ AudioRegion::normalize_to (float target_dB) { const jack_nframes_t blocksize = 256 * 1048; Sample buf[blocksize]; + char workbuf[blocksize * 4]; jack_nframes_t fpos; jack_nframes_t fend; jack_nframes_t to_read; @@ -1304,7 +1305,7 @@ AudioRegion::normalize_to (float target_dB) /* read it in */ - if (source (n).read (buf, fpos, to_read) != to_read) { + if (source (n).read (buf, fpos, to_read, workbuf) != to_read) { return; } diff --git a/libs/ardour/crossfade.cc b/libs/ardour/crossfade.cc index 8aed204d71..c23689a3a3 100644 --- a/libs/ardour/crossfade.cc +++ b/libs/ardour/crossfade.cc @@ -373,7 +373,7 @@ Crossfade::compute (AudioRegion& a, AudioRegion& b, CrossfadeModel model) jack_nframes_t Crossfade::read_at (Sample *buf, Sample *mixdown_buffer, - float *gain_buffer, jack_nframes_t start, jack_nframes_t cnt, uint32_t chan_n, + float *gain_buffer, char * workbuf, jack_nframes_t start, jack_nframes_t cnt, uint32_t chan_n, jack_nframes_t read_frames, jack_nframes_t skip_frames) { jack_nframes_t offset; @@ -409,8 +409,8 @@ Crossfade::read_at (Sample *buf, Sample *mixdown_buffer, offset = start - _position; - _out->read_at (crossfade_buffer_out, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames); - _in->read_at (crossfade_buffer_in, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames); + _out->read_at (crossfade_buffer_out, mixdown_buffer, gain_buffer, workbuf, start, to_write, chan_n, read_frames, skip_frames); + _in->read_at (crossfade_buffer_in, mixdown_buffer, gain_buffer, workbuf, start, to_write, chan_n, read_frames, skip_frames); float* fiv = new float[to_write]; float* fov = new float[to_write]; diff --git a/libs/ardour/destructive_filesource.cc b/libs/ardour/destructive_filesource.cc index 6df6ff06af..8715c5f283 100644 --- a/libs/ardour/destructive_filesource.cc +++ b/libs/ardour/destructive_filesource.cc @@ -66,8 +66,8 @@ gain_t* DestructiveFileSource::out_coefficient = 0; gain_t* DestructiveFileSource::in_coefficient = 0; jack_nframes_t DestructiveFileSource::xfade_frames = 64; -DestructiveFileSource::DestructiveFileSource (string path, jack_nframes_t rate, bool repair_first) - : FileSource (path, rate, repair_first) +DestructiveFileSource::DestructiveFileSource (string path, jack_nframes_t rate, bool repair_first, SampleFormat samp_format) + : FileSource (path, rate, repair_first, samp_format) { if (out_coefficient == 0) { setup_standard_crossfades (rate); @@ -118,7 +118,7 @@ int DestructiveFileSource::seek (jack_nframes_t frame) { // file_pos = data_offset + (sizeof (Sample) * frame); - cerr << _name << " Seek to " << frame << " = " << data_offset + (sizeof (Sample) * frame) << endl; + cerr << _name << " Seek to " << frame << " = " << data_offset + (_sample_size * frame) << endl; return 0; } @@ -143,41 +143,37 @@ DestructiveFileSource::clear_capture_marks () } jack_nframes_t -DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in) +DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in, char * workbuf) { jack_nframes_t xfade = min (xfade_frames, cnt); - jack_nframes_t xfade_bytes = xfade * sizeof (Sample); jack_nframes_t nofade = cnt - xfade; - jack_nframes_t nofade_bytes = nofade * sizeof (Sample); Sample* fade_data = 0; - off_t fade_position = 0; - + off_t fade_position = 0; // in frames + ssize_t retval; + if (fade_in) { fade_position = file_pos; fade_data = data; } else { - fade_position = file_pos + nofade_bytes; + fade_position = file_pos + nofade; fade_data = data + nofade; } - if (::pread64 (fd, (char *) xfade_buf, xfade_bytes, fade_position) != (off64_t) xfade_bytes) { - if (errno == EAGAIN) { + if ((retval = file_read (xfade_buf, fade_position, xfade, workbuf)) != (ssize_t) xfade) { + if (retval < 0 && errno == EAGAIN) { /* no data there, so no xfade */ xfade = 0; - xfade_bytes = 0; nofade = cnt; - nofade_bytes = nofade * sizeof (Sample); - } else { error << string_compose(_("FileSource: \"%1\" bad read (%2: %3)"), _path, errno, strerror (errno)) << endmsg; return 0; } } - + if (nofade && !fade_in) { - cerr << "write " << nofade_bytes << " of prefade OUT data to " << file_pos << " .. " << file_pos + nofade_bytes << endl; - if (::pwrite64 (fd, (char *) data, nofade_bytes, file_pos) != (off64_t) nofade_bytes) { + cerr << "write " << nofade << " frames of prefade OUT data to " << file_pos << " .. " << file_pos + nofade << endl; + if (file_write (data, file_pos, nofade, workbuf) != (ssize_t) nofade) { error << string_compose(_("FileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg; return 0; } @@ -219,17 +215,18 @@ DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in) } if (xfade) { - cerr << "write " << xfade_bytes << " of xfade data to " << fade_position << " .. " << fade_position + xfade_bytes << endl; - if (::pwrite64 (fd, (char *) xfade_buf, xfade_bytes, fade_position) != (off64_t) xfade_bytes) { + cerr << "write " << xfade << " frames of xfade data to " << fade_position << " .. " << fade_position + xfade << endl; + + if (file_write (xfade_buf, fade_position, xfade, workbuf) != (ssize_t) xfade) { error << string_compose(_("FileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg; return 0; } } if (fade_in && nofade) { - cerr << "write " << nofade_bytes << " of postfade IN data to " << file_pos + xfade_bytes << " .. " - << file_pos + xfade_bytes + nofade_bytes << endl; - if (::pwrite64 (fd, (char *) (data + xfade), nofade_bytes, file_pos + xfade_bytes) != (off64_t) nofade_bytes) { + cerr << "write " << nofade << " frames of postfade IN data to " << file_pos + xfade << " .. " + << file_pos + xfade + nofade << endl; + if (file_write (data + xfade, file_pos + xfade, nofade, workbuf) != (ssize_t) nofade) { error << string_compose(_("FileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg; return 0; } @@ -239,14 +236,13 @@ DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in) } jack_nframes_t -DestructiveFileSource::write (Sample* data, jack_nframes_t cnt) +DestructiveFileSource::write (Sample* data, jack_nframes_t cnt, char * workbuf) { cerr << _name << ": write " << cnt << " to " << file_pos << " start ? " << _capture_start << " end ? " << _capture_end << endl; { LockMonitor lm (_lock, __LINE__, __FILE__); - int32_t byte_cnt = cnt * sizeof (Sample); jack_nframes_t oldlen; if (_capture_start) { @@ -254,11 +250,12 @@ DestructiveFileSource::write (Sample* data, jack_nframes_t cnt) _capture_end = false; /* move to the correct location place */ - file_pos = data_offset + (capture_start_frame * sizeof (Sample)); - - cerr << "First byte of capture will be at " << file_pos << endl; + //file_pos = data_offset + (capture_start_frame * sizeof (Sample)); + file_pos = capture_start_frame; + + cerr << "First frame of capture will be at " << file_pos << endl; - if (crossfade (data, cnt, 1) != cnt) { + if (crossfade (data, cnt, 1, workbuf) != cnt) { return 0; } @@ -266,12 +263,11 @@ DestructiveFileSource::write (Sample* data, jack_nframes_t cnt) _capture_start = false; _capture_end = false; - if (crossfade (data, cnt, 0) != cnt) { + if (crossfade (data, cnt, 0, workbuf) != cnt) { return 0; } } else { - if (::pwrite64 (fd, (char *) data, byte_cnt, file_pos) != (off64_t) byte_cnt) { - error << string_compose(_("FileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg; + if (file_write(data, file_pos, cnt, workbuf) != (ssize_t) cnt) { return 0; } } @@ -280,8 +276,7 @@ DestructiveFileSource::write (Sample* data, jack_nframes_t cnt) if (file_pos + cnt > _length) { _length += cnt; } - _write_data_count = byte_cnt; - file_pos += byte_cnt; + file_pos += cnt; cerr << "at end of write, file_pos = " << file_pos << endl; diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index 154e085858..30f365ae32 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -992,6 +992,7 @@ DiskStream::overwrite_existing_buffers () { Sample* mixdown_buffer; float* gain_buffer; + char * workbuf; int ret = -1; bool reversed = (_visible_speed * _session.transport_speed()) < 0.0f; @@ -1002,7 +1003,8 @@ DiskStream::overwrite_existing_buffers () mixdown_buffer = new Sample[size]; gain_buffer = new float[size]; - + workbuf = new char[size*4]; + /* reduce size so that we can fill the buffer correctly. */ size--; @@ -1027,7 +1029,7 @@ DiskStream::overwrite_existing_buffers () jack_nframes_t to_read = size - overwrite_offset; - if (read ((*chan).playback_buf->buffer() + overwrite_offset, mixdown_buffer, gain_buffer, + if (read ((*chan).playback_buf->buffer() + overwrite_offset, mixdown_buffer, gain_buffer, workbuf, start, to_read, *chan, n, reversed)) { error << string_compose(_("DiskStream %1: when refilling, cannot read %2 from playlist at frame %3"), _id, size, playback_sample) << endmsg; @@ -1038,7 +1040,7 @@ DiskStream::overwrite_existing_buffers () cnt -= to_read; - if (read ((*chan).playback_buf->buffer(), mixdown_buffer, gain_buffer, + if (read ((*chan).playback_buf->buffer(), mixdown_buffer, gain_buffer, workbuf, start, cnt, *chan, n, reversed)) { error << string_compose(_("DiskStream %1: when refilling, cannot read %2 from playlist at frame %3"), _id, size, playback_sample) << endmsg; @@ -1053,6 +1055,7 @@ DiskStream::overwrite_existing_buffers () pending_overwrite = false; delete [] gain_buffer; delete [] mixdown_buffer; + delete [] workbuf; return ret; } @@ -1076,9 +1079,9 @@ DiskStream::seek (jack_nframes_t frame, bool complete_refill) file_frame = frame; if (complete_refill) { - while ((ret = do_refill (0, 0)) > 0); + while ((ret = do_refill (0, 0, 0)) > 0); } else { - ret = do_refill (0, 0); + ret = do_refill (0, 0, 0); } return ret; @@ -1113,8 +1116,7 @@ DiskStream::internal_playback_seek (jack_nframes_t distance) } int -DiskStream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, jack_nframes_t& start, jack_nframes_t cnt, - +DiskStream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, char * workbuf, jack_nframes_t& start, jack_nframes_t cnt, ChannelInfo& channel_info, int channel, bool reversed) { jack_nframes_t this_read = 0; @@ -1171,7 +1173,7 @@ DiskStream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, jack_ this_read = min(cnt,this_read); - if (_playlist->read (buf+offset, mixdown_buffer, gain_buffer, start, this_read, channel) != this_read) { + if (_playlist->read (buf+offset, mixdown_buffer, gain_buffer, workbuf, start, this_read, channel) != this_read) { error << string_compose(_("DiskStream %1: cannot read %2 from playlist at frame %3"), _id, this_read, start) << endmsg; return -1; @@ -1205,13 +1207,14 @@ DiskStream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, jack_ } int -DiskStream::do_refill (Sample* mixdown_buffer, float* gain_buffer) +DiskStream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * workbuf) { int32_t ret = 0; jack_nframes_t to_read; RingBufferNPT<Sample>::rw_vector vector; bool free_mixdown; bool free_gain; + bool free_workbuf; bool reversed = (_visible_speed * _session.transport_speed()) < 0.0f; jack_nframes_t total_space; jack_nframes_t zero_fill; @@ -1346,6 +1349,13 @@ DiskStream::do_refill (Sample* mixdown_buffer, float* gain_buffer) free_gain = false; } + if (workbuf == 0) { + workbuf = new char[disk_io_chunk_frames * 4]; + free_workbuf = true; + } else { + free_workbuf = false; + } + jack_nframes_t file_frame_tmp = 0; for (chan_n = 0, i = channels.begin(); i != channels.end(); ++i, ++chan_n) { @@ -1378,7 +1388,7 @@ DiskStream::do_refill (Sample* mixdown_buffer, float* gain_buffer) if (to_read) { - if (read (buf1, mixdown_buffer, gain_buffer, file_frame_tmp, to_read, chan, chan_n, reversed)) { + if (read (buf1, mixdown_buffer, gain_buffer, workbuf, file_frame_tmp, to_read, chan, chan_n, reversed)) { ret = -1; goto out; } @@ -1396,7 +1406,7 @@ DiskStream::do_refill (Sample* mixdown_buffer, float* gain_buffer) so read some or all of vector.len[1] as well. */ - if (read (buf2, mixdown_buffer, gain_buffer, file_frame_tmp, to_read, chan, chan_n, reversed)) { + if (read (buf2, mixdown_buffer, gain_buffer, workbuf, file_frame_tmp, to_read, chan, chan_n, reversed)) { ret = -1; goto out; } @@ -1419,12 +1429,15 @@ DiskStream::do_refill (Sample* mixdown_buffer, float* gain_buffer) if (free_gain) { delete [] gain_buffer; } + if (free_workbuf) { + delete [] workbuf; + } return ret; } int -DiskStream::do_flush (bool force_flush) +DiskStream::do_flush (char * workbuf, bool force_flush) { uint32_t to_write; int32_t ret = 0; @@ -1470,7 +1483,7 @@ DiskStream::do_flush (bool force_flush) to_write = min (disk_io_chunk_frames, (jack_nframes_t) vector.len[0]); - if ((!(*chan).write_source) || (*chan).write_source->write (vector.buf[0], to_write) != to_write) { + if ((!(*chan).write_source) || (*chan).write_source->write (vector.buf[0], to_write, workbuf) != to_write) { error << string_compose(_("DiskStream %1: cannot write to disk"), _id) << endmsg; return -1; } @@ -1486,7 +1499,7 @@ DiskStream::do_flush (bool force_flush) to_write = min ((jack_nframes_t)(disk_io_chunk_frames - to_write), (jack_nframes_t) vector.len[1]); - if ((*chan).write_source->write (vector.buf[1], to_write) != to_write) { + if ((*chan).write_source->write (vector.buf[1], to_write, workbuf) != to_write) { error << string_compose(_("DiskStream %1: cannot write to disk"), _id) << endmsg; return -1; } @@ -1539,7 +1552,7 @@ DiskStream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture */ while (more_work && !err) { - switch (do_flush (true)) { + switch (do_flush ( _session.conversion_buffer(Session::TransportContext), true)) { case 0: more_work = false; break; diff --git a/libs/ardour/filesource.cc b/libs/ardour/filesource.cc index 780f26fed6..1f3a89557c 100644 --- a/libs/ardour/filesource.cc +++ b/libs/ardour/filesource.cc @@ -65,6 +65,7 @@ #include <ardour/filesource.h> #include <ardour/session.h> #include <ardour/cycle_timer.h> +#include <ardour/pcm_utils.h> #include "i18n.h" @@ -101,10 +102,16 @@ 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 (); } @@ -119,6 +126,9 @@ FileSource::FileSource (string pathstr, jack_nframes_t rate, bool repair_first) 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(); } @@ -558,12 +568,19 @@ FileSource::fill_header (jack_nframes_t rate) 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 */ @@ -788,9 +805,18 @@ FileSource::read_broadcast_data (ChunkInfo& info) 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 << string_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; @@ -932,73 +958,38 @@ FileSource::mark_for_remove () } 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; } - - if (header.bigendian != WE_ARE_BIGENDIAN) { - swap_endian(dst, cnt); - } - _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 << string_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; @@ -1031,6 +1022,152 @@ FileSource::write (Sample *data, jack_nframes_t cnt) 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) { diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc index 3411481a3a..f5884a1c1d 100644 --- a/libs/ardour/import.cc +++ b/libs/ardour/import.cc @@ -42,7 +42,7 @@ using namespace ARDOUR; -#define BLOCKSIZE 2048U +#define BLOCKSIZE 4096U int Session::import_audiofile (import_status& status) @@ -53,6 +53,7 @@ Session::import_audiofile (import_status& status) SF_INFO info; float *data = 0; Sample **channel_data = 0; + char * workbuf = 0; long nfiles = 0; long n; string basepath; @@ -147,7 +148,8 @@ Session::import_audiofile (import_status& status) data = new float[BLOCKSIZE * info.channels]; channel_data = new Sample * [ info.channels ]; - + workbuf = new char[BLOCKSIZE * 4]; + for (n = 0; n < info.channels; ++n) { channel_data[n] = new Sample[BLOCKSIZE]; } @@ -178,7 +180,7 @@ Session::import_audiofile (import_status& status) /* flush to disk */ for (chn = 0; chn < info.channels; ++chn) { - newfiles[chn]->write (channel_data[chn], nread); + newfiles[chn]->write (channel_data[chn], nread, workbuf); } so_far += nread; @@ -245,7 +247,10 @@ Session::import_audiofile (import_status& status) if (data) { delete [] data; } - + if (workbuf) { + delete [] workbuf; + } + if (channel_data) { for (n = 0; n < info.channels; ++n) { delete [] channel_data[n]; diff --git a/libs/ardour/insert.cc b/libs/ardour/insert.cc index 3b3999a848..3ef84d1481 100644 --- a/libs/ardour/insert.cc +++ b/libs/ardour/insert.cc @@ -599,7 +599,7 @@ PluginInsert::state (bool full) node->add_property("id", string(buf)); if (_plugins[0]->state_node_name() == "ladspa") { char buf[32]; - snprintf (buf, 31, "%d", _plugins[0]->get_info().unique_id); + snprintf (buf, 31, "%ld", _plugins[0]->get_info().unique_id); node->add_property("unique-id", string(buf)); } node->add_property("count", string_compose("%1", _plugins.size())); diff --git a/libs/ardour/pcm_utils.cc b/libs/ardour/pcm_utils.cc new file mode 100644 index 0000000000..dd18fe8690 --- /dev/null +++ b/libs/ardour/pcm_utils.cc @@ -0,0 +1,178 @@ +/* + Copyright (C) 2006 Paul Davis , portions Erik de Castro Lopo + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include <ardour/pcm_utils.h> + +#include <cmath> + +using namespace std; + +// TODO: check CPU_CLIPS_POSITIVE and CPU_CLIPS_NEGATIVE with scons +#define CPU_CLIPS_NEGATIVE 0 +#define CPU_CLIPS_POSITIVE 0 + +/* these routines deal with 24 bit int handling (tribytes) + * originally from libsndfile, but modified. XXX - Copyright Erik de Castro Lopo + */ + +void +pcm_let2f_array (tribyte *src, int count, float *dest) +{ + /* Special normfactor because tribyte value is read into an int. */ + static const float normfact = 1.0 / ((float) 0x80000000); + + unsigned char *ucptr ; + int value ; + + ucptr = ((unsigned char*) src) + 3 * count ; + while (--count >= 0) + { ucptr -= 3 ; + value = LET2H_INT_PTR (ucptr) ; + dest [count] = ((float) value) * normfact ; + } ; +} /* let2f_array */ + +void +pcm_bet2f_array (tribyte *src, int count, float *dest) +{ + /* Special normfactor because tribyte value is read into an int. */ + static const float normfact = 1.0 / ((float) 0x80000000); + + unsigned char *ucptr ; + int value ; + + + ucptr = ((unsigned char*) src) + 3 * count ; + while (--count >= 0) + { ucptr -= 3 ; + value = BET2H_INT_PTR (ucptr) ; + dest [count] = ((float) value) * normfact ; + } ; +} /* bet2f_array */ + +void +pcm_f2let_array (float *src, tribyte *dest, int count) +{ + static const float normfact = (1.0 * 0x7FFFFF); + + unsigned char *ucptr ; + int value ; + + ucptr = ((unsigned char*) dest) + 3 * count ; + + while (count) + { count -- ; + ucptr -= 3 ; + value = lrintf (src [count] * normfact) ; + ucptr [0] = value ; + ucptr [1] = value >> 8 ; + ucptr [2] = value >> 16 ; + } ; +} /* f2let_array */ + +void +pcm_f2let_clip_array (float *src, tribyte *dest, int count) +{ + static const float normfact = (8.0 * 0x10000000); + + unsigned char *ucptr ; + float scaled_value ; + int value ; + + ucptr = ((unsigned char*) dest) + 3 * count ; + + while (count) + { count -- ; + ucptr -= 3 ; + scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + { ucptr [0] = 0xFF ; + ucptr [1] = 0xFF ; + ucptr [2] = 0x7F ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { ucptr [0] = 0x00 ; + ucptr [1] = 0x00 ; + ucptr [2] = 0x80 ; + continue ; + } ; + + value = lrintf (scaled_value) ; + ucptr [0] = value >> 8 ; + ucptr [1] = value >> 16 ; + ucptr [2] = value >> 24 ; + } ; +} /* f2let_clip_array */ + +void +pcm_f2bet_array (const float *src, tribyte *dest, int count) +{ + static const float normfact = (1.0 * 0x7FFFFF); + + unsigned char *ucptr ; + int value ; + + ucptr = ((unsigned char*) dest) + 3 * count ; + + while (--count >= 0) + { ucptr -= 3 ; + value = lrintf (src [count] * normfact) ; + ucptr [0] = value >> 16 ; + ucptr [1] = value >> 8 ; + ucptr [2] = value ; + } ; +} /* f2bet_array */ + +void +pcm_f2bet_clip_array (const float *src, tribyte *dest, int count) +{ + static const float normfact = (8.0 * 0x10000000); + + unsigned char *ucptr ; + float scaled_value ; + int value ; + + ucptr = ((unsigned char*) dest) + 3 * count ; + + while (--count >= 0) + { ucptr -= 3 ; + scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + { ucptr [0] = 0x7F ; + ucptr [1] = 0xFF ; + ucptr [2] = 0xFF ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { ucptr [0] = 0x80 ; + ucptr [1] = 0x00 ; + ucptr [2] = 0x00 ; + continue ; + } ; + + value = lrint (scaled_value) ; + ucptr [0] = value >> 24 ; + ucptr [1] = value >> 16 ; + ucptr [2] = value >> 8 ; + } ; +} /* f2bet_clip_array */ + +//@@@@@@@ diff --git a/libs/ardour/plugin.cc b/libs/ardour/plugin.cc index 059cf133a5..e9665908a3 100644 --- a/libs/ardour/plugin.cc +++ b/libs/ardour/plugin.cc @@ -273,7 +273,7 @@ Plugin::get_presets() lrdf_uris* set_uris = lrdf_get_setting_uris(unique_id()); if (set_uris) { - for (uint32_t i = 0; i < set_uris->count; ++i) { + for (uint32_t i = 0; i < (uint32_t) set_uris->count; ++i) { if (char* label = lrdf_get_label(set_uris->items[i])) { labels.push_back(label); presets[label] = set_uris->items[i]; @@ -294,10 +294,10 @@ Plugin::load_preset(const string preset_label) lrdf_defaults* defs = lrdf_get_setting_values(presets[preset_label].c_str()); if (defs) { - for (uint32_t i = 0; i < defs->count; ++i) { + for (uint32_t i = 0; i < (uint32_t) defs->count; ++i) { // The defs->items[i].pid < defs->count check is to work around // a bug in liblrdf that saves invalid values into the presets file. - if (((uint32_t) defs->items[i].pid < defs->count) && parameter_is_input (defs->items[i].pid)) { + if (((uint32_t) defs->items[i].pid < (uint32_t) defs->count) && parameter_is_input (defs->items[i].pid)) { set_parameter(defs->items[i].pid, defs->items[i].value); } } diff --git a/libs/ardour/reverse.cc b/libs/ardour/reverse.cc index 2474e0cb8d..335dacad6e 100644 --- a/libs/ardour/reverse.cc +++ b/libs/ardour/reverse.cc @@ -49,6 +49,7 @@ Reverse::run (AudioRegion& region) AudioRegion::SourceList::iterator si; const jack_nframes_t blocksize = 256 * 1048; Sample buf[blocksize]; + char * workbuf = 0;; jack_nframes_t fpos; jack_nframes_t fend; jack_nframes_t fstart; @@ -61,6 +62,8 @@ Reverse::run (AudioRegion& region) goto out; } + workbuf = new char[blocksize * 4]; + fend = region.start() + region.length(); fstart = region.start(); @@ -82,7 +85,7 @@ Reverse::run (AudioRegion& region) /* read it in */ - if (region.source (n).read (buf, fpos, to_read) != to_read) { + if (region.source (n).read (buf, fpos, to_read, workbuf) != to_read) { goto out; } @@ -94,7 +97,7 @@ Reverse::run (AudioRegion& region) /* write it out */ - if ((*si)->write (buf, to_read) != to_read) { + if ((*si)->write (buf, to_read, workbuf) != to_read) { goto out; } } @@ -120,6 +123,9 @@ Reverse::run (AudioRegion& region) delete *si; } } - + if (workbuf) { + delete [] workbuf; + } + return ret; } diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index b329c16cc6..e0c6c1bf7e 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -389,6 +389,10 @@ Session::~Session () free(*i); } + for (map<RunContext,char*>::iterator i = _conversion_buffers.begin(); i != _conversion_buffers.end(); ++i) { + delete [] (i->second); + } + #undef TRACK_DESTRUCTION #ifdef TRACK_DESTRUCTION cerr << "delete named selections\n"; @@ -1867,7 +1871,7 @@ void Session::add_diskstream (DiskStream* dstream) { /* need to do this in case we're rolling at the time, to prevent false underruns */ - dstream->do_refill(0, 0); + dstream->do_refill(0, 0, 0); { RWLockMonitor lm (diskstream_lock, true, __LINE__, __FILE__); @@ -3408,6 +3412,7 @@ Session::write_one_track (AudioTrack& track, jack_nframes_t start, jack_nframes_ jack_nframes_t this_chunk; jack_nframes_t to_do; vector<Sample*> buffers; + char * workbuf = 0; const jack_nframes_t chunk_size = (256 * 1024)/4; atomic_set (&processing_prohibited, 1); @@ -3470,18 +3475,20 @@ Session::write_one_track (AudioTrack& track, jack_nframes_t start, jack_nframes_ #endif buffers.push_back (b); } + + workbuf = new char[chunk_size * 4]; while (to_do && !itt.cancel) { this_chunk = min (to_do, chunk_size); - if (track.export_stuff (buffers, nchans, start, this_chunk)) { + if (track.export_stuff (buffers, workbuf, nchans, start, this_chunk)) { goto out; } uint32_t n = 0; for (vector<Source*>::iterator src=srcs.begin(); src != srcs.end(); ++src, ++n) { - if ((*src)->write (buffers[n], this_chunk) != this_chunk) { + if ((*src)->write (buffers[n], this_chunk, workbuf) != this_chunk) { goto out; } } @@ -3525,6 +3532,10 @@ Session::write_one_track (AudioTrack& track, jack_nframes_t start, jack_nframes_ free(*i); } + if (workbuf) { + delete [] workbuf; + } + atomic_set (&processing_prohibited, 0); itt.done = true; diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc index 12a838b5dd..00a2465d9b 100644 --- a/libs/ardour/session_butler.cc +++ b/libs/ardour/session_butler.cc @@ -174,6 +174,8 @@ Session::butler_thread_work () butler_mixdown_buffer = new Sample[DiskStream::disk_io_frames()]; butler_gain_buffer = new gain_t[DiskStream::disk_io_frames()]; + // this buffer is used for temp conversion purposes in filesources + char * conv_buffer = conversion_buffer(ButlerContext); while (true) { @@ -260,7 +262,7 @@ Session::butler_thread_work () // cerr << "rah fondr " << (*i)->io()->name () << endl; - switch ((*i)->do_refill (butler_mixdown_buffer, butler_gain_buffer)) { + switch ((*i)->do_refill (butler_mixdown_buffer, butler_gain_buffer, conv_buffer)) { case 0: bytes += (*i)->read_data_count(); break; @@ -303,7 +305,7 @@ Session::butler_thread_work () // cerr << "write behind for " << (*i)->name () << endl; - switch ((*i)->do_flush ()) { + switch ((*i)->do_flush (conv_buffer)) { case 0: bytes += (*i)->write_data_count(); break; diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 2a8bdf2fde..45a51e813b 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -190,6 +190,10 @@ Session::first_stage_init (string fullpath, string snapshot_name) pending_abort = false; layer_model = MoveAddHigher; xfade_model = ShortCrossfade; + + /* allocate conversion buffers */ + _conversion_buffers[ButlerContext] = new char[DiskStream::disk_io_frames() * 4]; + _conversion_buffers[TransportContext] = new char[DiskStream::disk_io_frames() * 4]; /* default short fade = 15ms */ diff --git a/libs/ardour/session_timefx.cc b/libs/ardour/session_timefx.cc index b8f0068a91..2fae4b32c9 100644 --- a/libs/ardour/session_timefx.cc +++ b/libs/ardour/session_timefx.cc @@ -93,6 +93,7 @@ Session::tempoize_region (TimeStretchRequest& tsr) for (uint32_t i = 0; i < sources.size(); ++i) { gain_t gain_buffer[bufsize]; Sample buffer[bufsize]; + char workbuf[bufsize*4]; jack_nframes_t pos = 0; jack_nframes_t this_read = 0; @@ -106,7 +107,7 @@ Session::tempoize_region (TimeStretchRequest& tsr) not the ones currently in use, in case it's already been subject to timefx. */ - if ((this_read = tsr.region->master_read_at (buffer, buffer, gain_buffer, pos + tsr.region->position(), this_time)) != this_time) { + if ((this_read = tsr.region->master_read_at (buffer, buffer, gain_buffer, workbuf, pos + tsr.region->position(), this_time)) != this_time) { error << string_compose (_("tempoize: error reading data from %1"), sources[i]->name()) << endmsg; goto out; } @@ -119,7 +120,7 @@ Session::tempoize_region (TimeStretchRequest& tsr) st.putSamples (buffer, this_read); while ((this_read = st.receiveSamples (buffer, bufsize)) > 0 && tsr.running) { - if (sources[i]->write (buffer, this_read) != this_read) { + if (sources[i]->write (buffer, this_read, workbuf) != this_read) { error << string_compose (_("error writing tempo-adjusted data to %1"), sources[i]->name()) << endmsg; goto out; } @@ -131,7 +132,7 @@ Session::tempoize_region (TimeStretchRequest& tsr) } while (tsr.running && (this_read = st.receiveSamples (buffer, bufsize)) > 0) { - if (sources[i]->write (buffer, this_read) != this_read) { + if (sources[i]->write (buffer, this_read, workbuf) != this_read) { error << string_compose (_("error writing tempo-adjusted data to %1"), sources[i]->name()) << endmsg; goto out; } diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc index 0baff36a3f..350a9c2ef1 100644 --- a/libs/ardour/sndfilesource.cc +++ b/libs/ardour/sndfilesource.cc @@ -122,13 +122,13 @@ SndFileSource::~SndFileSource () } jack_nframes_t -SndFileSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const +SndFileSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const { - return read (dst, start, cnt); + return read (dst, start, cnt, workbuf); } jack_nframes_t -SndFileSource::read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const +SndFileSource::read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const { int32_t nread; float *ptr; diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc index 515e8d4e9b..ee918375f6 100644 --- a/libs/ardour/source.cc +++ b/libs/ardour/source.cc @@ -419,7 +419,8 @@ Source::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start int ret = -1; PeakData* staging = 0; Sample* raw_staging = 0; - + char * workbuf = 0; + expected_peaks = (cnt / (double) frames_per_peak); scale = npeaks/expected_peaks; @@ -456,8 +457,9 @@ Source::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start */ Sample* raw_staging = new Sample[cnt]; + workbuf = new char[cnt*4]; - if (read_unlocked (raw_staging, start, cnt) != cnt) { + if (read_unlocked (raw_staging, start, cnt, workbuf) != cnt) { error << _("cannot read sample data for unscaled peak computation") << endmsg; return -1; } @@ -468,7 +470,7 @@ Source::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start } delete [] raw_staging; - + delete [] workbuf; return 0; } @@ -615,7 +617,8 @@ Source::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start jack_nframes_t nvisual_peaks = 0; jack_nframes_t chunksize = (jack_nframes_t) min (cnt, (jack_nframes_t) 4096); raw_staging = new Sample[chunksize]; - + workbuf = new char[chunksize *4]; + jack_nframes_t frame_pos = start; double pixel_pos = floor (frame_pos / samples_per_visual_peak); double next_pixel_pos = ceil (frame_pos / samples_per_visual_peak); @@ -630,7 +633,7 @@ Source::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start to_read = min (chunksize, (_length - current_frame)); - if ((frames_read = read_unlocked (raw_staging, current_frame, to_read)) < 0) { + if ((frames_read = read_unlocked (raw_staging, current_frame, to_read, workbuf)) < 0) { error << string_compose(_("Source[%1]: peak read - cannot read %2 samples at offset %3") , _name, to_read, current_frame) << endmsg; @@ -674,6 +677,10 @@ Source::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start delete [] raw_staging; } + if (workbuf) { + delete [] workbuf; + } + return ret; } @@ -743,6 +750,7 @@ Source::do_build_peak (jack_nframes_t first_frame, jack_nframes_t cnt) Sample xmin, xmax; uint32_t peaki; PeakData* peakbuf; + char * workbuf = 0; jack_nframes_t frames_read; jack_nframes_t frames_to_read; off_t first_peak_byte; @@ -762,11 +770,13 @@ Source::do_build_peak (jack_nframes_t first_frame, jack_nframes_t cnt) peakbuf = new PeakData[(cnt/frames_per_peak)+1]; peaki = 0; + workbuf = new char[max(frames_per_peak, cnt) * 4]; + while (cnt) { frames_to_read = min (frames_per_peak, cnt); - if ((frames_read = read_unlocked (buf, current_frame, frames_to_read)) != frames_to_read) { + if ((frames_read = read_unlocked (buf, current_frame, frames_to_read, workbuf)) != frames_to_read) { error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg; goto out; } @@ -800,6 +810,8 @@ Source::do_build_peak (jack_nframes_t first_frame, jack_nframes_t cnt) out: delete [] peakbuf; + if (workbuf) + delete [] workbuf; return ret; } diff --git a/libs/gtkmm2ext/pixscroller.cc b/libs/gtkmm2ext/pixscroller.cc index 556fce8080..8edf0723e1 100644 --- a/libs/gtkmm2ext/pixscroller.cc +++ b/libs/gtkmm2ext/pixscroller.cc @@ -33,7 +33,7 @@ PixScroller::PixScroller (Adjustment& a, Pix& pix) : adj (a) { dragging = false; - add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK); + add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK); adj.signal_value_changed().connect (mem_fun (*this, &PixScroller::adjustment_changed)); default_value = adj.get_value(); |