1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1992-2001 by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All rights reserved. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 30*7c478bd9Sstevel@tonic-gate #include <memory.h> 31*7c478bd9Sstevel@tonic-gate #include "../include/AudioDebug.h" 32*7c478bd9Sstevel@tonic-gate #include "../include/AudioBuffer.h" 33*7c478bd9Sstevel@tonic-gate #include "../include/zmalloc.h" 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate // class AudioBuffer methods 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate // Constructor with optional hdr, size, and name arguments 38*7c478bd9Sstevel@tonic-gate AudioBuffer:: 39*7c478bd9Sstevel@tonic-gate AudioBuffer( 40*7c478bd9Sstevel@tonic-gate double len, // buffer length, in seconds 41*7c478bd9Sstevel@tonic-gate const char *local_name): // name 42*7c478bd9Sstevel@tonic-gate AudioStream(local_name), buflen(len), bufaddr(0), zflag(0), bufsize(0) 43*7c478bd9Sstevel@tonic-gate { 44*7c478bd9Sstevel@tonic-gate } 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate // Destructor 47*7c478bd9Sstevel@tonic-gate AudioBuffer:: 48*7c478bd9Sstevel@tonic-gate ~AudioBuffer() 49*7c478bd9Sstevel@tonic-gate { 50*7c478bd9Sstevel@tonic-gate (void) SetSize(0.); // deallocate the buffer 51*7c478bd9Sstevel@tonic-gate } 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate // XXX - the following functions are good candidates for inlining 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate // Return TRUE if the stream is 'open' 56*7c478bd9Sstevel@tonic-gate Boolean AudioBuffer:: 57*7c478bd9Sstevel@tonic-gate opened() const 58*7c478bd9Sstevel@tonic-gate { 59*7c478bd9Sstevel@tonic-gate // A buffer is open if it is allocated and has a valid header 60*7c478bd9Sstevel@tonic-gate return (hdrset() && (GetAddress() != 0)); 61*7c478bd9Sstevel@tonic-gate } 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate #define MIN_ZBUFFER (8192 * 10) // only for large buffers 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate // Allocate buffer. Size and header must be set. 66*7c478bd9Sstevel@tonic-gate AudioError AudioBuffer:: 67*7c478bd9Sstevel@tonic-gate alloc() 68*7c478bd9Sstevel@tonic-gate { 69*7c478bd9Sstevel@tonic-gate long size; 70*7c478bd9Sstevel@tonic-gate size_t cnt; 71*7c478bd9Sstevel@tonic-gate unsigned int ncpy; 72*7c478bd9Sstevel@tonic-gate void* tmpbuf; 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate // this is going to be the size we're setting the buffer 75*7c478bd9Sstevel@tonic-gate // to (buflen field). it's set by calling SetSize(). 76*7c478bd9Sstevel@tonic-gate size = GetHeader().Time_to_Bytes(GetSize()); 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate // this is actual current size, in bytes, of the allocated 79*7c478bd9Sstevel@tonic-gate // buffer (the bufsize field). 80*7c478bd9Sstevel@tonic-gate cnt = GetByteCount(); 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate AUDIO_DEBUG((5, "%d: AudioBuffer::alloc - change from %d to %d bytes\n", 83*7c478bd9Sstevel@tonic-gate getid(), cnt, size)); 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate bufsize = 0; 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate if (size == 0) { 88*7c478bd9Sstevel@tonic-gate // Zero size deletes the buffer 89*7c478bd9Sstevel@tonic-gate if (bufaddr != 0) { 90*7c478bd9Sstevel@tonic-gate if (zflag != 0) { 91*7c478bd9Sstevel@tonic-gate AUDIO_DEBUG((5, 92*7c478bd9Sstevel@tonic-gate "%d: AudioBuffer::alloc - zfree mmapped buffer\n", 93*7c478bd9Sstevel@tonic-gate getid())); 94*7c478bd9Sstevel@tonic-gate (void) zfree((char *)bufaddr); 95*7c478bd9Sstevel@tonic-gate } else { 96*7c478bd9Sstevel@tonic-gate AUDIO_DEBUG((5, 97*7c478bd9Sstevel@tonic-gate "%d: AudioBuffer::alloc - free malloc'd buffer\n", 98*7c478bd9Sstevel@tonic-gate getid())); 99*7c478bd9Sstevel@tonic-gate (void) free((char *)bufaddr); 100*7c478bd9Sstevel@tonic-gate } 101*7c478bd9Sstevel@tonic-gate zflag = 0; 102*7c478bd9Sstevel@tonic-gate } 103*7c478bd9Sstevel@tonic-gate bufaddr = 0; 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate } else if (size < 0) { 106*7c478bd9Sstevel@tonic-gate // Ridiculous size 107*7c478bd9Sstevel@tonic-gate AUDIO_DEBUG((5, "%d: AudioBuffer::alloc - bad size\n", 108*7c478bd9Sstevel@tonic-gate getid())); 109*7c478bd9Sstevel@tonic-gate return (RaiseError(AUDIO_ERR_BADARG)); 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate } else if (bufaddr == 0) { 112*7c478bd9Sstevel@tonic-gate // Allocate a new buffer 113*7c478bd9Sstevel@tonic-gate if (size > MIN_ZBUFFER) { 114*7c478bd9Sstevel@tonic-gate AUDIO_DEBUG((5, 115*7c478bd9Sstevel@tonic-gate "%d: AudioBuffer::alloc - zmalloc new buffer\n", 116*7c478bd9Sstevel@tonic-gate getid())); 117*7c478bd9Sstevel@tonic-gate bufaddr = (void*) zmalloc((unsigned int)size); 118*7c478bd9Sstevel@tonic-gate zflag = 1; 119*7c478bd9Sstevel@tonic-gate } else { 120*7c478bd9Sstevel@tonic-gate AUDIO_DEBUG((5, 121*7c478bd9Sstevel@tonic-gate "%d: AudioBuffer::alloc - malloc new buffer\n", 122*7c478bd9Sstevel@tonic-gate getid())); 123*7c478bd9Sstevel@tonic-gate bufaddr = (void*) malloc((unsigned int)size); 124*7c478bd9Sstevel@tonic-gate zflag = 0; 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate if (bufaddr == 0) { 127*7c478bd9Sstevel@tonic-gate AUDIO_DEBUG((5, 128*7c478bd9Sstevel@tonic-gate "%d: AudioBuffer::alloc - buffer alloc failed\n", 129*7c478bd9Sstevel@tonic-gate getid())); 130*7c478bd9Sstevel@tonic-gate return (RaiseError(AUDIO_UNIXERROR)); 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate } else { 133*7c478bd9Sstevel@tonic-gate // A buffer was already allocated. 134*7c478bd9Sstevel@tonic-gate // Change its size, preserving as much data as possible. 135*7c478bd9Sstevel@tonic-gate if ((cnt <= MIN_ZBUFFER) && (size <= MIN_ZBUFFER) && 136*7c478bd9Sstevel@tonic-gate (zflag == 0)) { 137*7c478bd9Sstevel@tonic-gate AUDIO_DEBUG((5, 138*7c478bd9Sstevel@tonic-gate "%d: AudioBuffer::alloc - realloc to change size\n", 139*7c478bd9Sstevel@tonic-gate getid())); 140*7c478bd9Sstevel@tonic-gate bufaddr = (void*) 141*7c478bd9Sstevel@tonic-gate realloc((char *)bufaddr, (unsigned int)size); 142*7c478bd9Sstevel@tonic-gate } else { 143*7c478bd9Sstevel@tonic-gate AUDIO_DEBUG((5, 144*7c478bd9Sstevel@tonic-gate "%d: AudioBuffer::alloc - zmalloc new buffer\n", 145*7c478bd9Sstevel@tonic-gate getid())); 146*7c478bd9Sstevel@tonic-gate tmpbuf = bufaddr; 147*7c478bd9Sstevel@tonic-gate bufaddr = (void*) zmalloc((unsigned int)size); 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate // copy over as much of the old data as will fit 150*7c478bd9Sstevel@tonic-gate if (bufaddr != 0) { 151*7c478bd9Sstevel@tonic-gate ncpy = (cnt < size) ? (unsigned int)cnt : 152*7c478bd9Sstevel@tonic-gate (unsigned int)size; 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate AUDIO_DEBUG((5, 155*7c478bd9Sstevel@tonic-gate "%d: AudioBuffer::alloc - trasnfer %d bytes\n", 156*7c478bd9Sstevel@tonic-gate getid(), ncpy)); 157*7c478bd9Sstevel@tonic-gate (void) memcpy(bufaddr, tmpbuf, ncpy); 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate if ((cnt > MIN_ZBUFFER) && (zflag != 0)) { 160*7c478bd9Sstevel@tonic-gate AUDIO_DEBUG((5, 161*7c478bd9Sstevel@tonic-gate "%d: AudioBuffer::alloc - zfree old buffer\n", 162*7c478bd9Sstevel@tonic-gate getid())); 163*7c478bd9Sstevel@tonic-gate (void) zfree((char *)tmpbuf); 164*7c478bd9Sstevel@tonic-gate } else { 165*7c478bd9Sstevel@tonic-gate AUDIO_DEBUG((5, 166*7c478bd9Sstevel@tonic-gate "%d: AudioBuffer::alloc - free old buffer\n", 167*7c478bd9Sstevel@tonic-gate getid())); 168*7c478bd9Sstevel@tonic-gate (void) free((char *)tmpbuf); 169*7c478bd9Sstevel@tonic-gate } 170*7c478bd9Sstevel@tonic-gate zflag = 1; 171*7c478bd9Sstevel@tonic-gate } 172*7c478bd9Sstevel@tonic-gate if (bufaddr == 0) { 173*7c478bd9Sstevel@tonic-gate return (RaiseError(AUDIO_UNIXERROR)); 174*7c478bd9Sstevel@tonic-gate } 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate bufsize = (size_t)size; 177*7c478bd9Sstevel@tonic-gate return (AUDIO_SUCCESS); 178*7c478bd9Sstevel@tonic-gate } 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate // Return the buffer address 182*7c478bd9Sstevel@tonic-gate void* AudioBuffer:: 183*7c478bd9Sstevel@tonic-gate GetAddress() const 184*7c478bd9Sstevel@tonic-gate { 185*7c478bd9Sstevel@tonic-gate return (GetAddress(0.)); 186*7c478bd9Sstevel@tonic-gate } 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate // Return the buffer address at a given time offset 189*7c478bd9Sstevel@tonic-gate // Returns NULL if no buffer, or the position is not within the buffer. 190*7c478bd9Sstevel@tonic-gate void* AudioBuffer:: 191*7c478bd9Sstevel@tonic-gate GetAddress( 192*7c478bd9Sstevel@tonic-gate Double pos) const 193*7c478bd9Sstevel@tonic-gate { 194*7c478bd9Sstevel@tonic-gate char *addr; 195*7c478bd9Sstevel@tonic-gate AudioHdr hdr_local; 196*7c478bd9Sstevel@tonic-gate AudioHdr(AudioBuffer::*hfunc)()const; 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate addr = (char *)bufaddr; 199*7c478bd9Sstevel@tonic-gate if ((addr == 0) || (pos < 0.) || (pos >= buflen)) 200*7c478bd9Sstevel@tonic-gate return (NULL); 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate // If no offset, it's ok if the header hasn't been set yet 203*7c478bd9Sstevel@tonic-gate if (pos == 0.) 204*7c478bd9Sstevel@tonic-gate return ((void*) addr); 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate // Get the header and make sure it's valid 207*7c478bd9Sstevel@tonic-gate // This convoluted hfunc works around non-const function problems 208*7c478bd9Sstevel@tonic-gate hfunc = (AudioHdr(AudioBuffer::*)() const)&AudioBuffer::GetHeader; 209*7c478bd9Sstevel@tonic-gate hdr_local = (this->*hfunc)(); 210*7c478bd9Sstevel@tonic-gate if (hdr_local.Validate()) 211*7c478bd9Sstevel@tonic-gate return (NULL); 212*7c478bd9Sstevel@tonic-gate addr += hdr_local.Time_to_Bytes(pos); 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate // One more validation, to be paranoid before handing out this address 215*7c478bd9Sstevel@tonic-gate if (addr >= ((char *)bufaddr + bufsize)) 216*7c478bd9Sstevel@tonic-gate return (NULL); 217*7c478bd9Sstevel@tonic-gate return ((void*) addr); 218*7c478bd9Sstevel@tonic-gate } 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate // Return the buffer size, in bytes 221*7c478bd9Sstevel@tonic-gate // (as opposed to 'length' which indicates how much data is in the buffer) 222*7c478bd9Sstevel@tonic-gate size_t AudioBuffer:: 223*7c478bd9Sstevel@tonic-gate GetByteCount() const 224*7c478bd9Sstevel@tonic-gate { 225*7c478bd9Sstevel@tonic-gate return (bufsize); 226*7c478bd9Sstevel@tonic-gate } 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate // Return the buffer size, in seconds 229*7c478bd9Sstevel@tonic-gate // (as opposed to 'length' which indicates how much data is in the buffer) 230*7c478bd9Sstevel@tonic-gate Double AudioBuffer:: 231*7c478bd9Sstevel@tonic-gate GetSize() const 232*7c478bd9Sstevel@tonic-gate { 233*7c478bd9Sstevel@tonic-gate return (buflen); 234*7c478bd9Sstevel@tonic-gate } 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate // Set the buffer size, allocating the buffer as necessary 237*7c478bd9Sstevel@tonic-gate AudioError AudioBuffer:: 238*7c478bd9Sstevel@tonic-gate SetSize( 239*7c478bd9Sstevel@tonic-gate Double len) // new size, in seconds 240*7c478bd9Sstevel@tonic-gate { 241*7c478bd9Sstevel@tonic-gate // If no change in size, do nothing 242*7c478bd9Sstevel@tonic-gate if (len == buflen) 243*7c478bd9Sstevel@tonic-gate return (AUDIO_SUCCESS); 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate // If header not set, store the size for later 246*7c478bd9Sstevel@tonic-gate buflen = len; 247*7c478bd9Sstevel@tonic-gate if (!hdrset()) { 248*7c478bd9Sstevel@tonic-gate return (AUDIO_SUCCESS); 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate // If shrinking buffer, note this 252*7c478bd9Sstevel@tonic-gate if (buflen < GetLength()) 253*7c478bd9Sstevel@tonic-gate SetLength(buflen); 254*7c478bd9Sstevel@tonic-gate return (alloc()); 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate // Set the data header 258*7c478bd9Sstevel@tonic-gate // If no buffer allocated, allocate one now (if size is set). 259*7c478bd9Sstevel@tonic-gate // If buffer allocated, fiddle the sizes to account for new header type. 260*7c478bd9Sstevel@tonic-gate AudioError AudioBuffer:: 261*7c478bd9Sstevel@tonic-gate SetHeader( 262*7c478bd9Sstevel@tonic-gate const AudioHdr& h) // header to copy 263*7c478bd9Sstevel@tonic-gate { 264*7c478bd9Sstevel@tonic-gate AudioError err; 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate // Validate, then update the header 267*7c478bd9Sstevel@tonic-gate err = h.Validate(); 268*7c478bd9Sstevel@tonic-gate if (err) 269*7c478bd9Sstevel@tonic-gate return (RaiseError(err)); 270*7c478bd9Sstevel@tonic-gate (void) AudioStream::updateheader(h); 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate // If no size set, done for now 273*7c478bd9Sstevel@tonic-gate if (buflen == 0.) 274*7c478bd9Sstevel@tonic-gate return (AUDIO_SUCCESS); 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate // If no buffer allocated, allocate one now 277*7c478bd9Sstevel@tonic-gate if (GetAddress() == 0) 278*7c478bd9Sstevel@tonic-gate return (alloc()); 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate // If buffer allocated, change size to match new header 281*7c478bd9Sstevel@tonic-gate buflen = h.Bytes_to_Time(GetByteCount()); 282*7c478bd9Sstevel@tonic-gate return (AUDIO_SUCCESS); 283*7c478bd9Sstevel@tonic-gate } 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate // Set the buffer length (ie, the amount of data written to the buffer) 286*7c478bd9Sstevel@tonic-gate void AudioBuffer:: 287*7c478bd9Sstevel@tonic-gate SetLength( 288*7c478bd9Sstevel@tonic-gate Double len) // new length 289*7c478bd9Sstevel@tonic-gate { 290*7c478bd9Sstevel@tonic-gate if (!hdrset() || (len < 0.)) // no-op if not ready 291*7c478bd9Sstevel@tonic-gate return; 292*7c478bd9Sstevel@tonic-gate if (!opened() && (len > 0.)) 293*7c478bd9Sstevel@tonic-gate return; 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate if (Undefined(len) || (len > GetSize())) { 296*7c478bd9Sstevel@tonic-gate // Limit to the size of the buffer 297*7c478bd9Sstevel@tonic-gate setlength(GetSize()); 298*7c478bd9Sstevel@tonic-gate } else { 299*7c478bd9Sstevel@tonic-gate setlength(len); 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate // Copy data from local buffer into specified buffer. 304*7c478bd9Sstevel@tonic-gate // No data format translation takes place. 305*7c478bd9Sstevel@tonic-gate // The object's read position is not updated. 306*7c478bd9Sstevel@tonic-gate AudioError AudioBuffer:: 307*7c478bd9Sstevel@tonic-gate ReadData( 308*7c478bd9Sstevel@tonic-gate void* buf, // destination buffer address 309*7c478bd9Sstevel@tonic-gate size_t& len, // buffer length (updated) 310*7c478bd9Sstevel@tonic-gate Double& pos) // start position (updated) 311*7c478bd9Sstevel@tonic-gate { 312*7c478bd9Sstevel@tonic-gate off_t resid; 313*7c478bd9Sstevel@tonic-gate off_t cnt; 314*7c478bd9Sstevel@tonic-gate off_t offset; 315*7c478bd9Sstevel@tonic-gate AudioError err; 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate // Copy length, zero return value 318*7c478bd9Sstevel@tonic-gate cnt = (off_t)len; 319*7c478bd9Sstevel@tonic-gate len = 0; 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate // Cannot read if buffer or header not valid 322*7c478bd9Sstevel@tonic-gate if (!opened()) 323*7c478bd9Sstevel@tonic-gate return (RaiseError(AUDIO_ERR_NOEFFECT)); 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate // Position must be valid 326*7c478bd9Sstevel@tonic-gate if ((pos < 0.) || (cnt < 0)) 327*7c478bd9Sstevel@tonic-gate return (RaiseError(AUDIO_ERR_BADARG)); 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate // If the starting offset is at or beyond EOF, return eof flag 330*7c478bd9Sstevel@tonic-gate if (pos >= GetLength()) { 331*7c478bd9Sstevel@tonic-gate err = AUDIO_EOF; 332*7c478bd9Sstevel@tonic-gate err.sys = AUDIO_COPY_INPUT_EOF; 333*7c478bd9Sstevel@tonic-gate return (err); 334*7c478bd9Sstevel@tonic-gate } 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate // Limit transfer to remaining room in buffer 337*7c478bd9Sstevel@tonic-gate offset = GetHeader().Time_to_Bytes(pos); 338*7c478bd9Sstevel@tonic-gate resid = GetHeader().Time_to_Bytes(GetLength()) - offset; 339*7c478bd9Sstevel@tonic-gate if (resid <= 0) { 340*7c478bd9Sstevel@tonic-gate err = AUDIO_EOF; 341*7c478bd9Sstevel@tonic-gate err.sys = AUDIO_COPY_INPUT_EOF; 342*7c478bd9Sstevel@tonic-gate return (err); 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate if (cnt > resid) 345*7c478bd9Sstevel@tonic-gate cnt = resid; 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate // Fix the alignment to make sure we're not splitting frames 348*7c478bd9Sstevel@tonic-gate err = AUDIO_SUCCESS; 349*7c478bd9Sstevel@tonic-gate if (GetHeader().Bytes_to_Bytes(cnt) > 0) { 350*7c478bd9Sstevel@tonic-gate // Copy as much data as possible 351*7c478bd9Sstevel@tonic-gate memcpy((char *)buf, (char *)((off_t)GetAddress() + offset), 352*7c478bd9Sstevel@tonic-gate (int)cnt); 353*7c478bd9Sstevel@tonic-gate } else { 354*7c478bd9Sstevel@tonic-gate err.sys = AUDIO_COPY_ZERO_LIMIT; 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate // Return the updated transfer size and position 358*7c478bd9Sstevel@tonic-gate len = (size_t)cnt; 359*7c478bd9Sstevel@tonic-gate pos = GetHeader().Bytes_to_Time(offset + cnt); 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate // Check to see if the endian is right. 363*7c478bd9Sstevel@tonic-gate coerceEndian((unsigned char *)buf, len, localByteOrder()); 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate return (err); 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate // Copy data to local buffer from specified buffer. 369*7c478bd9Sstevel@tonic-gate // No data format translation takes place. 370*7c478bd9Sstevel@tonic-gate // The object's write position is not updated. 371*7c478bd9Sstevel@tonic-gate AudioError AudioBuffer:: 372*7c478bd9Sstevel@tonic-gate WriteData( 373*7c478bd9Sstevel@tonic-gate void* buf, // source buffer address 374*7c478bd9Sstevel@tonic-gate size_t& len, // buffer length (updated) 375*7c478bd9Sstevel@tonic-gate Double& pos) // start position (updated) 376*7c478bd9Sstevel@tonic-gate { 377*7c478bd9Sstevel@tonic-gate off_t resid; 378*7c478bd9Sstevel@tonic-gate off_t cnt; 379*7c478bd9Sstevel@tonic-gate off_t offset; 380*7c478bd9Sstevel@tonic-gate AudioError err; 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate // Copy length, zero return value 383*7c478bd9Sstevel@tonic-gate cnt = (off_t)len; 384*7c478bd9Sstevel@tonic-gate len = 0; 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate // Cannot write if buffer or header not valid 387*7c478bd9Sstevel@tonic-gate if (!opened()) 388*7c478bd9Sstevel@tonic-gate return (RaiseError(AUDIO_ERR_NOEFFECT)); 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate // Position must be valid 391*7c478bd9Sstevel@tonic-gate if ((pos < 0.) || (cnt < 0)) 392*7c478bd9Sstevel@tonic-gate return (RaiseError(AUDIO_ERR_BADARG)); 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate // If the starting offset beyond end of buffer, return short write flag 395*7c478bd9Sstevel@tonic-gate if (pos >= GetSize()) { 396*7c478bd9Sstevel@tonic-gate err = AUDIO_EOF; 397*7c478bd9Sstevel@tonic-gate err.sys = AUDIO_COPY_OUTPUT_EOF; 398*7c478bd9Sstevel@tonic-gate return (err); 399*7c478bd9Sstevel@tonic-gate } 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate // Limit transfer to remaining room in buffer 402*7c478bd9Sstevel@tonic-gate offset = GetHeader().Time_to_Bytes(pos); 403*7c478bd9Sstevel@tonic-gate resid = (off_t)bufsize - offset; 404*7c478bd9Sstevel@tonic-gate if (resid <= 0) { 405*7c478bd9Sstevel@tonic-gate err = AUDIO_EOF; 406*7c478bd9Sstevel@tonic-gate err.sys = AUDIO_COPY_OUTPUT_EOF; 407*7c478bd9Sstevel@tonic-gate return (err); 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate if (cnt > resid) 410*7c478bd9Sstevel@tonic-gate cnt = resid; 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate // Fix the alignment to make sure we're not splitting frames 413*7c478bd9Sstevel@tonic-gate err = AUDIO_SUCCESS; 414*7c478bd9Sstevel@tonic-gate if (GetHeader().Bytes_to_Bytes(cnt) > 0) { 415*7c478bd9Sstevel@tonic-gate // Copy as much data as possible 416*7c478bd9Sstevel@tonic-gate memcpy((char *)((off_t)GetAddress() + offset), (char *)buf, 417*7c478bd9Sstevel@tonic-gate (int)cnt); 418*7c478bd9Sstevel@tonic-gate } else { 419*7c478bd9Sstevel@tonic-gate err.sys = AUDIO_COPY_ZERO_LIMIT; 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate // Return the updated transfer size and position 423*7c478bd9Sstevel@tonic-gate len = (size_t)cnt; 424*7c478bd9Sstevel@tonic-gate pos = GetHeader().Bytes_to_Time(offset + cnt); 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate // The end of a write to a buffer always becomes the buffer EOF 427*7c478bd9Sstevel@tonic-gate setlength(pos); 428*7c478bd9Sstevel@tonic-gate return (err); 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate // AppendData is just like WriteData, except that it guarantees to extend 432*7c478bd9Sstevel@tonic-gate // the buffer if it is not big enough. 433*7c478bd9Sstevel@tonic-gate // The object's write position is not updated. 434*7c478bd9Sstevel@tonic-gate AudioError AudioBuffer:: 435*7c478bd9Sstevel@tonic-gate AppendData( 436*7c478bd9Sstevel@tonic-gate void* buf, // source buffer address 437*7c478bd9Sstevel@tonic-gate size_t& len, // buffer length (updated) 438*7c478bd9Sstevel@tonic-gate Double& pos) // start position (updated) 439*7c478bd9Sstevel@tonic-gate { 440*7c478bd9Sstevel@tonic-gate Double local_length; 441*7c478bd9Sstevel@tonic-gate AudioError err; 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate // Cannot write if header not valid 444*7c478bd9Sstevel@tonic-gate if (!hdrset()) 445*7c478bd9Sstevel@tonic-gate return (RaiseError(AUDIO_ERR_NOEFFECT)); 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate // Position must be valid 448*7c478bd9Sstevel@tonic-gate if (pos < 0.) 449*7c478bd9Sstevel@tonic-gate return (RaiseError(AUDIO_ERR_BADARG)); 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate // If the ending offset is beyond end of buffer, extend it 452*7c478bd9Sstevel@tonic-gate local_length = pos + GetHeader().Bytes_to_Time(len); 453*7c478bd9Sstevel@tonic-gate if (local_length > GetSize()) { 454*7c478bd9Sstevel@tonic-gate if (err = SetSize(local_length)) 455*7c478bd9Sstevel@tonic-gate return (err); 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate return (WriteData(buf, len, pos)); 458*7c478bd9Sstevel@tonic-gate } 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate // Copy routine to copy direct to destination 461*7c478bd9Sstevel@tonic-gate AudioError AudioBuffer:: 462*7c478bd9Sstevel@tonic-gate AsyncCopy( 463*7c478bd9Sstevel@tonic-gate Audio* to, // audio object to copy to 464*7c478bd9Sstevel@tonic-gate Double& frompos, 465*7c478bd9Sstevel@tonic-gate Double& topos, 466*7c478bd9Sstevel@tonic-gate Double& limit) 467*7c478bd9Sstevel@tonic-gate { 468*7c478bd9Sstevel@tonic-gate caddr_t bptr; 469*7c478bd9Sstevel@tonic-gate size_t cnt; 470*7c478bd9Sstevel@tonic-gate size_t svcnt; 471*7c478bd9Sstevel@tonic-gate Double svfrom; 472*7c478bd9Sstevel@tonic-gate Double svto; 473*7c478bd9Sstevel@tonic-gate Double lim; 474*7c478bd9Sstevel@tonic-gate AudioHdr tohdr; 475*7c478bd9Sstevel@tonic-gate AudioError err; 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate // Cannot write if buffer or header not valid 478*7c478bd9Sstevel@tonic-gate if (!opened()) 479*7c478bd9Sstevel@tonic-gate return (RaiseError(AUDIO_ERR_NOEFFECT)); 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate tohdr = to->GetHeader(); 482*7c478bd9Sstevel@tonic-gate if (limit < 0.) 483*7c478bd9Sstevel@tonic-gate return (RaiseError(AUDIO_ERR_BADARG)); 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate // Get maximum possible copy length 486*7c478bd9Sstevel@tonic-gate svfrom = GetLength(); 487*7c478bd9Sstevel@tonic-gate if (frompos >= svfrom) { 488*7c478bd9Sstevel@tonic-gate limit = 0.; 489*7c478bd9Sstevel@tonic-gate err = AUDIO_EOF; 490*7c478bd9Sstevel@tonic-gate err.sys = AUDIO_COPY_INPUT_EOF; 491*7c478bd9Sstevel@tonic-gate return (err); 492*7c478bd9Sstevel@tonic-gate } 493*7c478bd9Sstevel@tonic-gate lim = svfrom - frompos; 494*7c478bd9Sstevel@tonic-gate if (!Undefined(limit) && (limit < lim)) 495*7c478bd9Sstevel@tonic-gate lim = limit; 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate limit = 0.; 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate bptr = (caddr_t)GetAddress(frompos); 500*7c478bd9Sstevel@tonic-gate if (bptr == 0) { 501*7c478bd9Sstevel@tonic-gate err = AUDIO_EOF; 502*7c478bd9Sstevel@tonic-gate err.sys = AUDIO_COPY_INPUT_EOF; 503*7c478bd9Sstevel@tonic-gate return (err); 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate cnt = (size_t)GetHeader().Time_to_Bytes(lim); 506*7c478bd9Sstevel@tonic-gate if (cnt == 0) { 507*7c478bd9Sstevel@tonic-gate err = AUDIO_SUCCESS; 508*7c478bd9Sstevel@tonic-gate err.sys = AUDIO_COPY_ZERO_LIMIT; 509*7c478bd9Sstevel@tonic-gate return (err); 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate // Add a bunch of paranoid checks 513*7c478bd9Sstevel@tonic-gate svcnt = (size_t)GetAddress() + (size_t)GetByteCount(); 514*7c478bd9Sstevel@tonic-gate if ((bptr + cnt) > (caddr_t)svcnt) { 515*7c478bd9Sstevel@tonic-gate // re-adjust cnt so it reads up to the end of file 516*7c478bd9Sstevel@tonic-gate cnt = (size_t)((caddr_t)svcnt - bptr); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate if (GetHeader().Bytes_to_Bytes(cnt) == 0) { 519*7c478bd9Sstevel@tonic-gate err = AUDIO_EOF; 520*7c478bd9Sstevel@tonic-gate err.sys = AUDIO_COPY_INPUT_EOF; 521*7c478bd9Sstevel@tonic-gate return (err); 522*7c478bd9Sstevel@tonic-gate } 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate // Write the data to the destination and update pointers/ctrs 525*7c478bd9Sstevel@tonic-gate svfrom = frompos; 526*7c478bd9Sstevel@tonic-gate svto = topos; 527*7c478bd9Sstevel@tonic-gate svcnt = cnt; 528*7c478bd9Sstevel@tonic-gate err = to->WriteData(bptr, cnt, topos); 529*7c478bd9Sstevel@tonic-gate limit = topos - svto; 530*7c478bd9Sstevel@tonic-gate frompos = svfrom + limit; 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate // Report short writes 533*7c478bd9Sstevel@tonic-gate if (!err && (cnt < svcnt)) { 534*7c478bd9Sstevel@tonic-gate err.sys = AUDIO_COPY_SHORT_OUTPUT; 535*7c478bd9Sstevel@tonic-gate } 536*7c478bd9Sstevel@tonic-gate return (err); 537*7c478bd9Sstevel@tonic-gate } 538