Figure 5: Partial listing of file Signal.h, the Signal class implementation
#include "FIR.h" enum Fade_in_modes { linear, cosine_shaped }; template <class T> class Signal { public: // ************** Constructor ****************** Signal (int requested_size = 256, int fade_in_len = 10, Fade_in_modes mode = linear); // ********* Samples insertion methods ********* Signal<T> & operator<< (const T & value) { recent_sample_pos = (recent_sample_pos + 1) & mask; x[recent_sample_pos] = value; return *this; } void fade_in (const T & value); // definition omited here template <class Iterator> void insert_block (Iterator block_start, size_t block_size) { if (block_size > capacity() || block_size < 1) throw exception("Bad block_size in Signal::insert_block()"); if (recent_sample_pos + block_size < x.size()) { copy (block_start, block_start + block_size, &x[recent_sample_pos + 1]); recent_sample_pos += block_size; } else { copy (block_start, block_start + x.size() - recent_sample_pos - 1, &x[recent_sample_pos + 1]); copy (block_start + x.size() - recent_sample_pos - 1, block_start + block_size, &x[0]); recent_sample_pos += block_size - x.size(); } } // ************ Samples read methods ************ const T & operator[] (int subscript) const { if (subscript <= 0) return const_cast<Signal<T> *>(this) -> x[(recent_sample_pos + subscript) & mask]; else throw out_of_range("Subscript must be negative"); } const T & most_recent_sample () const { return const_cast <Signal<T> *>(this)->x[recent_sample_pos]; } const T & front () const { return most_recent_sample(); } // ************ Iterators *************** class iterator { friend class const_iterator; public: iterator (T * sig = NULL, int it = 0, int msk = 0) : signal(sig), iter(it), mask(msk) {} T & operator* () const { return signal[iter]; } // iter was already "ANDed" with mask in // all the iterator arithmetic operators const iterator & operator++ () { iter = (iter + 1) & mask; return *this; } const iterator operator+ (int offset) const { return iterator (signal, (iter+offset) & mask, mask); } // The rest of the operators are not shown here private: T * signal; int iter; int mask; }; // ** class const_iterator is not shown here, to save // ** magazine space; its definition is very similar // ** to that of iterator. iterator begin () { return iterator(&x[0], recent_sample_pos, mask); } const_iterator begin () const { return const_iterator (const_cast<Signal<T> *>(this)->begin()); } // ************ Filtering Functions ****************** template <class FilterCoeff> void filtered_output (const basic_FIR<FilterCoeff> & filter, T & result) const { if (recent_sample_pos >= filter.length() - 1) filter.output (&const_cast<Signal<T> *>(this) -> x[recent_sample_pos], result); else filter.output (begin(), result); } template <class FilterCoeff> T filtered_output (const basic_FIR<FilterCoeff> & filter) const { T result; filtered_output (filter, result); return result; } template <class FilterCoeff, class OutputIterator> void filtered_block (const basic_FIR<FilterCoeff> & filter, int num_samples, OutputIterator y) const { for (int i = -num_samples + 1; i <= 0; i++) if (((recent_sample_pos + i) & mask) >= filter.length()-1) filter.output (&const_cast<Signal<T> *>(this) -> x [(recent_sample_pos + i) & mask], *y++); else filter.output (begin() + i, *y++); } // ************** Misc. / Utility *************** int capacity () const { return size; } private: valarray<T> x; int mask, size, recent_sample_pos; Fade_in_modes fade_in_mode; int fade_in_counter, fade_in_length; }; // ************************************* // Member functions definitions // ************************************* template <class T> Signal<T>::Signal (int requested_size, int fade_len, Fade_in_modes mode) : size(requested_size), fade_in_length(fade_len), fade_in_mode(mode), recent_sample_pos(0), fade_in_counter(0) { mask = -1; while (mask & (size-1)) mask <<= 1; mask = ~mask; x.resize(mask + 1); x = T(); // Fill the buffer (a valarray) with zeroes }