00001 /* 00002 * This is the Loris C++ Class Library, implementing analysis, 00003 * manipulation, and synthesis of digitized sounds using the Reassigned 00004 * Bandwidth-Enhanced Additive Sound Model. 00005 * 00006 * Loris is Copyright (c) 1999-2004 by Kelly Fitz and Lippold Haken 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY, without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00021 * 00022 * 00023 * SpcFile.h 00024 * 00025 * Definition of SpcFile class for Partial import and export for 00026 * real-time synthesis in Kyma. 00027 * 00028 * Spc files always represent a number of Partials that is a power of 00029 * two. This is not necessary for purely-sinusoidal files, but might be 00030 * (not clear) for enhanced data to be properly processed in Kyma. 00031 * 00032 * All of this is kind of disgusting right now. This code has evolved 00033 * somewhat randomly, and we are awaiting full support for bandwidth- 00034 * enhanced data in Kyma.. 00035 * 00036 * Kelly Fitz, 8 Jan 2003 00037 * loris@cerlsoundgroup.org 00038 * 00039 * http://www.cerlsoundgroup.org/Loris/ 00040 * 00041 */ 00042 #include "Marker.h" 00043 #include "Partial.h" 00044 00045 #if defined(NO_TEMPLATE_MEMBERS) 00046 #include "PartialList.h" 00047 #endif 00048 00049 #include <string> 00050 #include <vector> 00051 00052 // begin namespace 00053 namespace Loris { 00054 00055 // --------------------------------------------------------------------------- 00056 // class SpcFile 00057 // 00058 // Class SpcFile represents a collection of reassigned bandwidth-enhanced 00059 // Partial data in a SPC-format envelope stream data file, used by the 00060 // real-time bandwidth-enhanced additive synthesizer implemented on the 00061 // Symbolic Sound Kyma Sound Design Workstation. Class SpcFile manages 00062 // file I/O and conversion between Partials and envelope parameter streams. 00063 // 00064 class SpcFile 00065 { 00066 // -- public interface -- 00067 public: 00068 00069 // -- types -- 00070 typedef std::vector< Marker > markers_type; 00071 typedef std::vector< Partial > partials_type; 00072 00073 // -- construction -- 00074 explicit SpcFile( const std::string & filename ); 00075 /* Initialize an instance of SpcFile by importing envelope parameter 00076 streams from the file having the specified filename or path. 00077 */ 00078 00079 #if !defined(NO_TEMPLATE_MEMBERS) 00080 template<typename Iter> 00081 SpcFile( Iter begin_partials, Iter end_partials, double midiNoteNum = 60 ); 00082 #else 00083 SpcFile( PartialList::const_iterator begin_partials, 00084 PartialList::const_iterator end_partials, 00085 double midiNoteNum = 60 ); 00086 #endif 00087 /* Initialize an instance of SpcFile with copies of the Partials 00088 on the specified half-open (STL-style) range. 00089 00090 If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts 00091 only PartialList::const_iterator arguments. 00092 */ 00093 00094 explicit SpcFile( double midiNoteNum = 60 ); 00095 /* Initialize an instance of SpcFile having the specified fractional 00096 MIDI note number, and no Partials (or envelope parameter streams). 00097 */ 00098 00099 // copy, assign, and delete are compiler-generated 00100 00101 // -- access -- 00102 markers_type & markers( void ); 00103 const markers_type & markers( void ) const; 00104 /* Return a reference to the MarkerContainer (see Marker.h) for this SpcFile. 00105 */ 00106 00107 double midiNoteNumber( void ) const; 00108 /* Return the fractional MIDI note number assigned to this SpcFile. 00109 If the sound has no definable pitch, note number 60.0 is used. 00110 */ 00111 00112 const partials_type & partials( void ) const; 00113 /* Return a read-only (const) reference to the bandwidth-enhanced 00114 Partials represented by the envelope parameter streams in this SpcFile. 00115 */ 00116 00117 double sampleRate( void ) const; 00118 /* Return the sampling freqency in Hz for the spc data in this 00119 SpcFile. This is the rate at which Kyma must be running to ensure 00120 proper playback of bandwidth-enhanced Spc data. 00121 */ 00122 00123 // -- mutation -- 00124 void addPartial( const Loris::Partial & p ); 00125 /* Add the specified Partial to the enevelope parameter streams 00126 represented by this SpcFile. 00127 00128 A SpcFile can contain only one Partial having any given (non-zero) 00129 label, so an added Partial will replace a Partial having the 00130 same label, if such a Partial exists. 00131 00132 This may throw an InvalidArgument exception if an attempt is made 00133 to add unlabeled Partials, or Partials labeled higher than the 00134 allowable maximum. 00135 */ 00136 00137 void addPartial( const Loris::Partial & p, int label ); 00138 /* Add a Partial, assigning it the specified label (and position in the 00139 Spc data). 00140 00141 A SpcFile can contain only one Partial having any given (non-zero) 00142 label, so an added Partial will replace a Partial having the 00143 same label, if such a Partial exists. 00144 00145 This may throw an InvalidArgument exception if an attempt is made 00146 to add unlabeled Partials, or Partials labeled higher than the 00147 allowable maximum. 00148 */ 00149 00150 #if !defined(NO_TEMPLATE_MEMBERS) 00151 template<typename Iter> 00152 void addPartials( Iter begin_partials, Iter end_partials ); 00153 #else 00154 void addPartials( PartialList::const_iterator begin_partials, 00155 PartialList::const_iterator end_partials ); 00156 #endif 00157 /* Add all Partials on the specified half-open (STL-style) range 00158 to the enevelope parameter streams represented by this SpcFile. 00159 00160 A SpcFile can contain only one Partial having any given (non-zero) 00161 label, so an added Partial will replace a Partial having the 00162 same label, if such a Partial exists. 00163 00164 If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts 00165 only PartialList::const_iterator arguments. 00166 00167 This may throw an InvalidArgument exception if an attempt is made 00168 to add unlabeled Partials, or Partials labeled higher than the 00169 allowable maximum. 00170 */ 00171 00172 void setMidiNoteNumber( double nn ); 00173 /* Set the fractional MIDI note number assigned to this SpcFile. 00174 If the sound has no definable pitch, use note number 60.0 (the default). 00175 */ 00176 00177 void setSampleRate( double rate ); 00178 /* Set the sampling freqency in Hz for the spc data in this 00179 SpcFile. This is the rate at which Kyma must be running to ensure 00180 proper playback of bandwidth-enhanced Spc data. 00181 00182 The default sample rate is 44100 Hz. 00183 */ 00184 00185 // -- export -- 00186 void write( const std::string & filename, double endApproachTime = 0 ); 00187 /* Export the phase-correct bandwidth-enhanced envelope parameter 00188 streams represented by this SpcFile to the file having the specified 00189 filename or path. 00190 00191 A nonzero endApproachTime indicates that the Partials do not include a 00192 release or decay, but rather end in a static spectrum corresponding to the 00193 final Breakpoint values of the partials. The endApproachTime specifies how 00194 long before the end of the sound the amplitude, frequency, and bandwidth 00195 values are to be modified to make a gradual transition to the static spectrum. 00196 00197 If the endApproachTime is not specified, it is assumed to be zero, 00198 corresponding to Partials that decay or release normally. 00199 */ 00200 00201 void writeSinusoidal( const std::string & filename, double endApproachTime = 0 ); 00202 /* Export the pure sinsoidal (omitting phase and bandwidth data) envelope 00203 parameter streams represented by this SpcFile to the file having the 00204 specified filename or path. 00205 00206 A nonzero endApproachTime indicates that the Partials do not include a 00207 release or decay, but rather end in a static spectrum corresponding to the 00208 final Breakpoint values of the partials. The endApproachTime specifies how 00209 long before the end of the sound the amplitude, frequency, and bandwidth 00210 values are to be modified to make a gradual transition to the static spectrum. 00211 00212 If the endApproachTime is not specified, it is assumed to be zero, 00213 corresponding to Partials that decay or release normally. 00214 */ 00215 00216 void write( const std::string & filename, bool enhanced, 00217 double endApproachTime = 0 ); 00218 /* Export the envelope parameter streams represented by this SpcFile to 00219 the file having the specified filename or path. Export phase-correct 00220 bandwidth-enhanced envelope parameter streams if enhanced is true 00221 (the default), or pure sinsoidal streams otherwise. 00222 00223 A nonzero endApproachTime indicates that the Partials do not include a 00224 release or decay, but rather end in a static spectrum corresponding to the 00225 final Breakpoint values of the partials. The endApproachTime specifies how 00226 long before the end of the sound the amplitude, frequency, and bandwidth 00227 values are to be modified to make a gradual transition to the static spectrum. 00228 00229 If the endApproachTime is not specified, it is assumed to be zero, 00230 corresponding to Partials that decay or release normally. 00231 00232 This version of write is deprecated, use the two-argument 00233 versions write and writeSinusoidal. 00234 */ 00235 00236 private: 00237 // -- implementation -- 00238 partials_type partials_; // Partials to store in Spc format 00239 markers_type markers_; // AIFF Markers 00240 00241 double notenum_, rate_; // MIDI note number and sample rate 00242 00243 static const int MinNumPartials; // 32 00244 static const double DefaultRate; // 44kHz 00245 00246 // -- helpers -- 00247 void readSpcData( const std::string & filename ); 00248 void growPartials( partials_type::size_type sz ); 00249 00250 }; // end of class SpcFile 00251 00252 00253 // --------------------------------------------------------------------------- 00254 // constructor from Partial range 00255 // --------------------------------------------------------------------------- 00256 // Initialize an instance of SpcFile with copies of the Partials 00257 // on the specified half-open (STL-style) range. If the MIDI 00258 // note number is not specified, then note number 60 is used. 00259 // 00260 // If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts 00261 // only PartialList::const_iterator arguments. 00262 // 00263 #if !defined(NO_TEMPLATE_MEMBERS) 00264 template< typename Iter > 00265 SpcFile::SpcFile( Iter begin_partials, Iter end_partials, double midiNoteNum ) : 00266 #else 00267 SpcFile::SpcFile( PartialList::const_iterator begin_partials, 00268 PartialList::const_iterator end_partials, 00269 double midiNoteNum ) : 00270 #endif 00271 // initializers: 00272 notenum_( midiNoteNum ), 00273 rate_( DefaultRate ) 00274 { 00275 growPartials( MinNumPartials ); 00276 addPartials( begin_partials, end_partials ); 00277 } 00278 00279 // --------------------------------------------------------------------------- 00280 // addPartials 00281 // --------------------------------------------------------------------------- 00282 // Add all Partials on the specified half-open (STL-style) range 00283 // to the enevelope parameter streams represented by this SpcFile. 00284 // 00285 // A SpcFile can contain only one Partial having any given (non-zero) 00286 // label, so an added Partial will replace a Partial having the 00287 // same label, if such a Partial exists. 00288 // 00289 // If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts 00290 // only PartialList::const_iterator arguments. 00291 // 00292 // This may throw an InvalidArgument exception if an attempt is made 00293 // to add unlabeled Partials, or Partials labeled higher than the 00294 // allowable maximum. 00295 // 00296 #if !defined(NO_TEMPLATE_MEMBERS) 00297 template<typename Iter> 00298 void SpcFile::addPartials( Iter begin_partials, Iter end_partials ) 00299 #else 00300 void SpcFile::addPartials( PartialList::const_iterator begin_partials, 00301 PartialList::const_iterator end_partials ) 00302 #endif 00303 { 00304 while ( begin_partials != end_partials ) 00305 { 00306 addPartial( *(begin_partials++) ); 00307 } 00308 } 00309 00310 } // end of namespace Loris 00311 00312
1.3.4