open_toontown_panda3d/panda/src/movies/userDataAudio.cxx

152 lines
5.1 KiB
C++

// Filename: userDataAudio.cxx
// Created by: jyelon (02Jul07)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "userDataAudio.h"
#include "userDataAudioCursor.h"
TypeHandle UserDataAudio::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: UserDataAudio::Constructor
// Access: Public
// Description: This constructor returns a UserDataAudio ---
// a means to supply raw audio samples manually.
////////////////////////////////////////////////////////////////////
UserDataAudio::
UserDataAudio(int rate, int channels, bool remove_after_read) :
MovieAudio("User Data Audio"),
_desired_rate(rate),
_desired_channels(channels),
_cursor(NULL),
_aborted(false),
_remove_after_read(remove_after_read)
{
}
////////////////////////////////////////////////////////////////////
// Function: UserDataAudio::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
UserDataAudio::
~UserDataAudio() {
}
////////////////////////////////////////////////////////////////////
// Function: UserDataAudio::open
// Access: Published, Virtual
// Description: Open this audio, returning a UserDataAudioCursor. A
// UserDataAudio can only be opened by one consumer
// at a time.
////////////////////////////////////////////////////////////////////
PT(MovieAudioCursor) UserDataAudio::
open() {
if (_cursor) {
nassert_raise("A UserDataAudio can only be opened by one consumer at a time.");
return NULL;
}
_cursor = new UserDataAudioCursor(this);
return _cursor;
}
////////////////////////////////////////////////////////////////////
// Function: UserDataAudio::read_samples
// Access: Private
// Description: Read audio samples from the stream. N is the
// number of samples you wish to read. Your buffer
// must be equal in size to N * channels.
// Multiple-channel audio will be interleaved.
////////////////////////////////////////////////////////////////////
void UserDataAudio::
read_samples(int n, PN_int16 *data) {
int ready = (_data.size() / _desired_channels);
int desired = n * _desired_channels;
int avail = ready * _desired_channels;
if (avail > desired) avail = desired;
for (int i=0; i<avail; i++) {
data[i] = _data[i];
}
for (int i=avail; i<desired; i++) {
data[i] = 0;
}
for (int i=0; i<avail; i++) {
_data.pop_front();
}
}
////////////////////////////////////////////////////////////////////
// Function: UserDataAudio::append
// Access: Public
// Description: Appends audio samples to the buffer.
////////////////////////////////////////////////////////////////////
void UserDataAudio::
append(PN_int16 *data, int n) {
nassertv(!_aborted);
int words = n * _desired_channels;
for (int i=0; i<words; i++) {
_data.push_back(data[i]);
}
}
////////////////////////////////////////////////////////////////////
// Function: UserDataAudio::append
// Access: Published
// Description: Appends audio samples to the buffer from a
// datagram. This is intended to make it easy to
// send streaming raw audio over a network.
////////////////////////////////////////////////////////////////////
void UserDataAudio::
append(DatagramIterator *src, int n) {
nassertv(!_aborted);
int maxlen = src->get_remaining_size() / (2 * _desired_channels);
if (n > maxlen) n = maxlen;
int words = n * _desired_channels;
for (int i=0; i<words; i++) {
_data.push_back(src->get_int16());
}
}
////////////////////////////////////////////////////////////////////
// Function: UserDataAudio::append
// Access: Published
// Description: Appends audio samples to the buffer from a
// string. The samples must be stored little-endian
// in the string. This is not particularly efficient,
// but it may be convenient to deal with samples in
// python.
////////////////////////////////////////////////////////////////////
void UserDataAudio::
append(const string &str) {
nassertv(!_aborted);
int samples = str.size() / (2 * _desired_channels);
int words = samples * _desired_channels;
for (int i=0; i<words; i++) {
int c1 = ((unsigned char)str[i*2+0]);
int c2 = ((unsigned char)str[i*2+1]);
PN_int16 n = (c1 | (c2 << 8));
_data.push_back(n);
}
}
////////////////////////////////////////////////////////////////////
// Function: UserDataAudio::done
// Access: Published
// Description: Promises not to append any more samples, ie, this
// marks the end of the audio stream.
////////////////////////////////////////////////////////////////////
void UserDataAudio::
done() {
_aborted = true;
}