github.com/256dpi/max-go@v0.7.0/lib/msp/ext_buffer.h (about) 1 #ifndef _EXT_BUFFER_H_ 2 #define _EXT_BUFFER_H_ 3 4 #include "ext_prefix.h" 5 #include "ext_mess.h" 6 7 /** A buffer~ reference. 8 Use this struct to represent a reference to a buffer~ object in Max. 9 Use the buffer_ref_getbuffer() call to return a pointer to the buffer. 10 You can then make calls on the buffer itself. 11 12 @ingroup buffers 13 */ 14 typedef struct _buffer_ref t_buffer_ref; 15 16 17 /** A buffer~ object. 18 This represents the actual buffer~ object. 19 You can use this to send messages, query attributes, etc. of the actual buffer object 20 referenced by a #t_buffer_ref. 21 22 @ingroup buffers 23 */ 24 typedef t_object t_buffer_obj; 25 26 27 /** Common buffer~ data/metadata. 28 This info can be retreived from a buffer~ using the buffer_getinfo() call. 29 30 @ingroup buffers 31 */ 32 typedef struct _buffer_info 33 { 34 t_symbol *b_name; ///< name of the buffer 35 float *b_samples; ///< stored with interleaved channels if multi-channel 36 long b_frames; ///< number of sample frames (each one is sizeof(float) * b_nchans bytes) 37 long b_nchans; ///< number of channels 38 long b_size; ///< size of buffer in floats 39 float b_sr; ///< sampling rate of the buffer 40 long b_modtime; ///< last modified time ("dirty" method) 41 long b_rfu[57]; ///< reserved for future use (total struct size is 64x4 = 256 bytes) 42 } t_buffer_info; 43 44 45 BEGIN_USING_C_LINKAGE 46 47 48 /** Create a reference to a buffer~ object by name. 49 You must release the buffer reference using object_free() when you are finished using it. 50 51 @ingroup buffers 52 @param self pointer to your object 53 @param name the name of the buffer~ 54 @return a pointer to your new buffer reference 55 */ 56 t_buffer_ref* buffer_ref_new(t_object *self, t_symbol *name); 57 58 59 /** Change a buffer reference to refer to a different buffer~ object by name. 60 61 @ingroup buffers 62 @param x the buffer reference 63 @param name the name of a different buffer~ to reference 64 */ 65 void buffer_ref_set(t_buffer_ref *x, t_symbol *name); 66 67 68 /** Query to find out if a buffer~ with the referenced name actually exists. 69 70 @ingroup buffers 71 @param x the buffer reference 72 @return non-zero if the buffer~ exists, otherwise zero 73 */ 74 t_atom_long buffer_ref_exists(t_buffer_ref *x); 75 76 77 /** Query a buffer reference to get the actual buffer~ object being referenced, if it exists. 78 79 @ingroup buffers 80 @param x the buffer reference 81 @return the buffer object if exists, otherwise NULL 82 */ 83 t_buffer_obj *buffer_ref_getobject(t_buffer_ref *x); 84 85 86 /** Your object needs to handle notifications issued by the buffer~ you reference. 87 You do this by defining a "notify" method. 88 Your notify method should then call this notify method for the #t_buffer_ref. 89 90 @ingroup buffers 91 @param x the buffer reference 92 @param s the registered name of the sending object 93 @param msg then name of the notification/message sent 94 @param sender the pointer to the sending object 95 @param data optional argument sent with the notification/message 96 @return a max error code 97 */ 98 t_max_err buffer_ref_notify(t_buffer_ref *x, t_symbol *s, t_symbol *msg, void *sender, void *data); 99 100 101 102 103 104 /** Open a viewer window to display the contents of the buffer~. 105 106 @ingroup buffers 107 @param buffer_object the buffer object 108 */ 109 void buffer_view(t_buffer_obj *buffer_object); 110 111 112 /** Claim the buffer~ and get a pointer to the first sample in memory. 113 When you are done reading/writing to the buffer you must call buffer_unlocksamples(). 114 If the attempt to claim the buffer~ fails the returned pointer will be NULL. 115 116 @ingroup buffers 117 @param buffer_object the buffer object 118 @return a pointer to the first sample in memory, or NULL if the buffer doesn't exist. 119 */ 120 float *buffer_locksamples(t_buffer_obj *buffer_object); 121 122 123 /** Release your claim on the buffer~ contents so that other objects may read/write to the buffer~. 124 125 @ingroup buffers 126 @param buffer_object the buffer object 127 */ 128 void buffer_unlocksamples(t_buffer_obj *buffer_object); 129 130 131 #ifndef C74_BUFFER_INTERNAL 132 133 134 /** Query a buffer~ to find out how many channels are present in the buffer content. 135 136 @ingroup buffers 137 @param buffer_object the buffer object 138 @return the number of channels in the buffer 139 */ 140 t_atom_long buffer_getchannelcount(t_buffer_obj *buffer_object); 141 142 143 /** Query a buffer~ to find out how many frames long the buffer content is in samples. 144 145 @ingroup buffers 146 @param buffer_object the buffer object 147 @return the number of frames in the buffer 148 */ 149 t_atom_long buffer_getframecount(t_buffer_obj *buffer_object); 150 151 152 /** Query a buffer~ to find out its native sample rate in samples per second. 153 154 @ingroup buffers 155 @param buffer_object the buffer object 156 @return the sample rate in samples per second 157 */ 158 t_atom_float buffer_getsamplerate(t_buffer_obj *buffer_object); 159 160 161 /** Query a buffer~ to find out its native sample rate in samples per millisecond. 162 163 @ingroup buffers 164 @param buffer_object the buffer object 165 @return the sample rate in samples per millisecond 166 */ 167 t_atom_float buffer_getmillisamplerate(t_buffer_obj *buffer_object); 168 169 170 /** Set the number of samples with which to zero-pad the buffer~'s contents. 171 The typical application for this need is to pad a buffer with enough room to allow for the reach of a FIR kernel in convolution. 172 173 @ingroup buffers 174 @param buffer_object the buffer object 175 @param samplecount the number of sample to pad the buffer with on each side of the contents 176 @return an error code 177 */ 178 t_max_err buffer_setpadding(t_buffer_obj *buffer_object, t_atom_long samplecount); 179 180 181 /** Set the buffer's dirty flag, indicating that changes have been made. 182 183 @ingroup buffers 184 @param buffer_object the buffer object 185 @return an error code 186 */ 187 t_max_err buffer_setdirty(t_buffer_obj *buffer_object); 188 189 190 /** Retrieve the name of the last file to be read by a buffer~. 191 (Not the last file written). 192 193 @ingroup buffers 194 @param buffer_object the buffer object 195 @return The name of the file last read, or gensym("") if no files have been read. 196 197 @version Introduced in Max 7.0.1 198 */ 199 t_symbol *buffer_getfilename(t_buffer_obj *buffer_object); 200 201 202 #endif // C74_BUFFER_INTERNAL 203 204 205 // Internal or low-level functions 206 207 208 // buffer_perform functions to replace the direct use of 209 // atomics and other buffer state flags from the perform method 210 // wrapped by buffer_locksamples() and buffer_unlocksamples() 211 t_max_err buffer_perform_begin(t_buffer_obj *buffer_object); 212 t_max_err buffer_perform_end(t_buffer_obj *buffer_object); 213 214 // utility function for getting buffer info in struct form 215 // without needing to know entire buffer struct 216 t_max_err buffer_getinfo(t_buffer_obj *buffer_object, t_buffer_info *info); 217 218 219 // the following functions are not to be called in the perform method 220 // please use the lightweight buffer_perform methods 221 222 // use buffer_edit functions to collapse all operations of 223 // locking heavy b_mutex, setting b_valid flag, 224 // waiting on lightweight atomic b_inuse, etc. 225 t_max_err buffer_edit_begin(t_buffer_obj *buffer_object); 226 t_max_err buffer_edit_end(t_buffer_obj *buffer_object, long valid); // valid 0=FALSE, positive=TRUE, negative=RESTORE_OLD_VALID (not common) 227 228 // low level mutex locking used by buffer_edit fucntions. 229 // use only if you really know what you're doing. 230 // otherwise, use the buffer_edit functions 231 // if you're touching a t_buffer outside perform 232 t_max_err buffer_lock(t_buffer_obj *buffer_object); 233 t_max_err buffer_trylock(t_buffer_obj *buffer_object); 234 t_max_err buffer_unlock(t_buffer_obj *buffer_object); 235 236 // low level utilities used by buffer_edit functions 237 // use only if you really know what you're doing. 238 // otherwise, use the buffer_edit functions 239 // if you're touching a t_buffer outside perform 240 t_buffer_obj *buffer_findowner(t_buffer_obj *buffer_object); 241 long buffer_spinwait(t_buffer_obj *buffer_object); 242 long buffer_valid(t_buffer_obj *buffer_object, long way); 243 244 245 246 247 END_USING_C_LINKAGE 248 249 250 #endif // #ifndef _EXT_BUFFER_H_