152 lines
5.1 KiB
C++
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;
|
|
}
|