00001 // Filename: userDataAudio.cxx 00002 // Created by: jyelon (02Jul07) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "userDataAudio.h" 00016 #include "userDataAudioCursor.h" 00017 00018 TypeHandle UserDataAudio::_type_handle; 00019 00020 //////////////////////////////////////////////////////////////////// 00021 // Function: UserDataAudio::Constructor 00022 // Access: Public 00023 // Description: This constructor returns a UserDataAudio --- 00024 // a means to supply raw audio samples manually. 00025 //////////////////////////////////////////////////////////////////// 00026 UserDataAudio:: 00027 UserDataAudio(int rate, int channels, bool remove_after_read) : 00028 MovieAudio("User Data Audio"), 00029 _desired_rate(rate), 00030 _desired_channels(channels), 00031 _cursor(NULL), 00032 _aborted(false), 00033 _remove_after_read(remove_after_read) 00034 { 00035 } 00036 00037 //////////////////////////////////////////////////////////////////// 00038 // Function: UserDataAudio::Destructor 00039 // Access: Public, Virtual 00040 // Description: 00041 //////////////////////////////////////////////////////////////////// 00042 UserDataAudio:: 00043 ~UserDataAudio() { 00044 } 00045 00046 //////////////////////////////////////////////////////////////////// 00047 // Function: UserDataAudio::open 00048 // Access: Published, Virtual 00049 // Description: Open this audio, returning a UserDataAudioCursor. A 00050 // UserDataAudio can only be opened by one consumer 00051 // at a time. 00052 //////////////////////////////////////////////////////////////////// 00053 PT(MovieAudioCursor) UserDataAudio:: 00054 open() { 00055 if (_cursor) { 00056 nassert_raise("A UserDataAudio can only be opened by one consumer at a time."); 00057 return NULL; 00058 } 00059 _cursor = new UserDataAudioCursor(this); 00060 return _cursor; 00061 } 00062 00063 //////////////////////////////////////////////////////////////////// 00064 // Function: UserDataAudio::read_samples 00065 // Access: Private 00066 // Description: Read audio samples from the stream. N is the 00067 // number of samples you wish to read. Your buffer 00068 // must be equal in size to N * channels. 00069 // Multiple-channel audio will be interleaved. 00070 //////////////////////////////////////////////////////////////////// 00071 void UserDataAudio:: 00072 read_samples(int n, PN_int16 *data) { 00073 int ready = (_data.size() / _desired_channels); 00074 int desired = n * _desired_channels; 00075 int avail = ready * _desired_channels; 00076 if (avail > desired) avail = desired; 00077 for (int i=0; i<avail; i++) { 00078 data[i] = _data[i]; 00079 } 00080 for (int i=avail; i<desired; i++) { 00081 data[i] = 0; 00082 } 00083 for (int i=0; i<avail; i++) { 00084 _data.pop_front(); 00085 } 00086 } 00087 00088 //////////////////////////////////////////////////////////////////// 00089 // Function: UserDataAudio::append 00090 // Access: Public 00091 // Description: Appends audio samples to the buffer. 00092 //////////////////////////////////////////////////////////////////// 00093 void UserDataAudio:: 00094 append(PN_int16 *data, int n) { 00095 nassertv(!_aborted); 00096 int words = n * _desired_channels; 00097 for (int i=0; i<words; i++) { 00098 _data.push_back(data[i]); 00099 } 00100 } 00101 00102 //////////////////////////////////////////////////////////////////// 00103 // Function: UserDataAudio::append 00104 // Access: Published 00105 // Description: Appends audio samples to the buffer from a 00106 // datagram. This is intended to make it easy to 00107 // send streaming raw audio over a network. 00108 //////////////////////////////////////////////////////////////////// 00109 void UserDataAudio:: 00110 append(DatagramIterator *src, int n) { 00111 nassertv(!_aborted); 00112 int maxlen = src->get_remaining_size() / (2 * _desired_channels); 00113 if (n > maxlen) n = maxlen; 00114 int words = n * _desired_channels; 00115 for (int i=0; i<words; i++) { 00116 _data.push_back(src->get_int16()); 00117 } 00118 } 00119 00120 //////////////////////////////////////////////////////////////////// 00121 // Function: UserDataAudio::append 00122 // Access: Published 00123 // Description: Appends audio samples to the buffer from a 00124 // string. The samples must be stored little-endian 00125 // in the string. This is not particularly efficient, 00126 // but it may be convenient to deal with samples in 00127 // python. 00128 //////////////////////////////////////////////////////////////////// 00129 void UserDataAudio:: 00130 append(const string &str) { 00131 nassertv(!_aborted); 00132 int samples = str.size() / (2 * _desired_channels); 00133 int words = samples * _desired_channels; 00134 for (int i=0; i<words; i++) { 00135 int c1 = ((unsigned char)str[i*2+0]); 00136 int c2 = ((unsigned char)str[i*2+1]); 00137 PN_int16 n = (c1 | (c2 << 8)); 00138 _data.push_back(n); 00139 } 00140 } 00141 00142 //////////////////////////////////////////////////////////////////// 00143 // Function: UserDataAudio::done 00144 // Access: Published 00145 // Description: Promises not to append any more samples, ie, this 00146 // marks the end of the audio stream. 00147 //////////////////////////////////////////////////////////////////// 00148 void UserDataAudio:: 00149 done() { 00150 _aborted = true; 00151 }