mirror of
https://github.com/thestk/stk
synced 2026-01-16 14:21:53 +00:00
Version 4.0
This commit is contained in:
committed by
Stephen Sinclair
parent
3f126af4e5
commit
81475b04c5
267
src/RtWvIn.cpp
267
src/RtWvIn.cpp
@@ -1,146 +1,121 @@
|
||||
/*******************************************/
|
||||
/* RtWvIn Input Class, */
|
||||
/* by Gary P. Scavone, 1999-2000 */
|
||||
/* */
|
||||
/* This object inherits from WvIn and is */
|
||||
/* used to read in realtime 16-bit data */
|
||||
/* from a computer's audio port. */
|
||||
/* */
|
||||
/* NOTE: This object is NOT intended for */
|
||||
/* use in achieving simultaneous realtime */
|
||||
/* audio input/output (together with */
|
||||
/* RtWvOut). Under certain circumstances */
|
||||
/* such a scheme is possible, though you */
|
||||
/* should definitely know what you are */
|
||||
/* doing before trying. For safer "full- */
|
||||
/* duplex" operation, use the RtDuplex */
|
||||
/* class. */
|
||||
/*******************************************/
|
||||
|
||||
#include "RtWvIn.h"
|
||||
|
||||
RtWvIn :: RtWvIn(int chans, MY_FLOAT srate, int device)
|
||||
{
|
||||
chunking = 1;
|
||||
looping = 0;
|
||||
sound_dev = new RtAudio(chans, srate, "record", device);
|
||||
channels = chans;
|
||||
bufferSize = RT_BUFFER_SIZE;
|
||||
data = 0;
|
||||
rtdata = (INT16 *) new INT16[(bufferSize+1)*channels];
|
||||
|
||||
lastSamples = (INT16 *) new INT16[channels];
|
||||
for (int i=0;i<channels;i++) {
|
||||
lastSamples[i] = (INT16) 0.0;
|
||||
}
|
||||
|
||||
this->getData(0);
|
||||
|
||||
rate = (MY_FLOAT) srate / SRATE;
|
||||
if (fmod(rate, 1.0) > 0.0) interpolate = 1;
|
||||
else interpolate = 0;
|
||||
phaseOffset = (MY_FLOAT) 0.0;
|
||||
lastOutput = (MY_FLOAT *) new MY_FLOAT[channels];
|
||||
this->reset();
|
||||
|
||||
gain = 0.00003052;
|
||||
#if (defined(__STK_REALTIME_) && defined(__OS_IRIX_))
|
||||
// This is necessary under IRIX because it scales the input by 0.5
|
||||
// when using single-channel input.
|
||||
if (channels == 1) gain *= 2;
|
||||
#endif
|
||||
}
|
||||
|
||||
RtWvIn :: ~RtWvIn()
|
||||
{
|
||||
delete sound_dev;
|
||||
if (rtdata) {
|
||||
delete [ ] rtdata;
|
||||
rtdata = 0;
|
||||
}
|
||||
if (lastSamples) {
|
||||
delete [ ] lastSamples;
|
||||
lastSamples = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void RtWvIn :: setRate(MY_FLOAT aRate)
|
||||
{
|
||||
// Negative rates not allowed for realtime input
|
||||
rate = fabs(aRate);
|
||||
|
||||
if (fmod(rate, 1.0) != 0.0) interpolate = 1;
|
||||
else interpolate = 0;
|
||||
}
|
||||
|
||||
void RtWvIn :: addTime(MY_FLOAT aTime)
|
||||
{
|
||||
// Negative time shift no allowed for realtime input
|
||||
time += fabs(aTime);
|
||||
}
|
||||
|
||||
void RtWvIn :: setLooping(int aLoopStatus)
|
||||
{
|
||||
// No looping for realtime data.
|
||||
looping = 0;
|
||||
}
|
||||
|
||||
long RtWvIn :: getSize()
|
||||
{
|
||||
return bufferSize;
|
||||
}
|
||||
|
||||
void RtWvIn :: getData(long index)
|
||||
{
|
||||
static long temp = RT_BUFFER_SIZE*channels;
|
||||
sound_dev->recordBuffer(&rtdata[channels],temp);
|
||||
|
||||
/* Fill in the extra sample frame for interpolation.
|
||||
* We do this by pre-pending the last sample frame
|
||||
* from the previous input buffer to the current one.
|
||||
*/
|
||||
for (int i=0;i<channels;i++) {
|
||||
rtdata[i] = lastSamples[i];
|
||||
lastSamples[i] = rtdata[temp+i];
|
||||
}
|
||||
}
|
||||
|
||||
int RtWvIn :: informTick()
|
||||
{
|
||||
static MY_FLOAT alpha;
|
||||
static long index;
|
||||
|
||||
if (time >= bufferSize) {
|
||||
this->getData(0);
|
||||
while (time >= bufferSize)
|
||||
time -= bufferSize;
|
||||
}
|
||||
|
||||
// integer part of time address
|
||||
index = (long) time;
|
||||
|
||||
if (interpolate) {
|
||||
// fractional part of time address
|
||||
alpha = time - (MY_FLOAT) index;
|
||||
index *= channels;
|
||||
for (int i=0;i<channels;i++) {
|
||||
// Do linear interpolation
|
||||
lastOutput[i] = (MY_FLOAT) rtdata[index];
|
||||
lastOutput[i] += alpha * ((MY_FLOAT) rtdata[index+channels] - lastOutput[i]);
|
||||
lastOutput[i] *= gain;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
index *= channels;
|
||||
for (int i=0;i<channels;i++) {
|
||||
lastOutput[i] = rtdata[index++];
|
||||
lastOutput[i] *= gain;
|
||||
}
|
||||
}
|
||||
|
||||
// increment time, which can be negative
|
||||
time += rate;
|
||||
|
||||
return finished;
|
||||
}
|
||||
/***************************************************/
|
||||
/*! \class RtWvIn
|
||||
\brief STK realtime audio input class.
|
||||
|
||||
This class provides a simplified interface to
|
||||
RtAudio for realtime audio input. It is a
|
||||
protected subclass of WvIn.
|
||||
|
||||
RtWvIn supports multi-channel data in
|
||||
interleaved format. It is important to
|
||||
distinguish the tick() methods, which return
|
||||
samples produced by averaging across sample
|
||||
frames, from the tickFrame() methods, which
|
||||
return pointers to multi-channel sample frames.
|
||||
For single-channel data, these methods return
|
||||
equivalent values.
|
||||
|
||||
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
|
||||
*/
|
||||
/***************************************************/
|
||||
|
||||
#include "RtWvIn.h"
|
||||
|
||||
RtWvIn :: RtWvIn(int nChannels, MY_FLOAT sampleRate, int device, int bufferFrames, int nBuffers )
|
||||
{
|
||||
channels = nChannels;
|
||||
int size = bufferFrames;
|
||||
RtAudio::RTAUDIO_FORMAT format = ( sizeof(MY_FLOAT) == 8 ) ? RtAudio::RTAUDIO_FLOAT64 : RtAudio::RTAUDIO_FLOAT32;
|
||||
try {
|
||||
audio = new RtAudio(&stream, 0, 0, device, channels, format,
|
||||
(int)sampleRate, &size, nBuffers);
|
||||
data = (MY_FLOAT *) audio->getStreamBuffer(stream);
|
||||
}
|
||||
catch (RtError &error) {
|
||||
handleError( error.getMessage(), StkError::AUDIO_SYSTEM );
|
||||
}
|
||||
|
||||
bufferSize = size;
|
||||
lastOutput = (MY_FLOAT *) new MY_FLOAT[channels];
|
||||
for (unsigned int i=0; i<channels; i++) lastOutput[i] = 0.0;
|
||||
counter = 0;
|
||||
stopped = true;
|
||||
}
|
||||
|
||||
RtWvIn :: ~RtWvIn()
|
||||
{
|
||||
if ( !stopped )
|
||||
audio->stopStream(stream);
|
||||
delete audio;
|
||||
data = 0; // RtAudio deletes the buffer itself.
|
||||
}
|
||||
|
||||
void RtWvIn :: start()
|
||||
{
|
||||
if ( stopped ) {
|
||||
audio->startStream(stream);
|
||||
stopped = false;
|
||||
}
|
||||
}
|
||||
|
||||
void RtWvIn :: stop()
|
||||
{
|
||||
if ( !stopped ) {
|
||||
audio->stopStream(stream);
|
||||
stopped = true;
|
||||
}
|
||||
}
|
||||
|
||||
MY_FLOAT RtWvIn :: lastOut(void) const
|
||||
{
|
||||
return WvIn::lastOut();
|
||||
}
|
||||
|
||||
MY_FLOAT RtWvIn :: tick(void)
|
||||
{
|
||||
tickFrame();
|
||||
return lastOut();
|
||||
}
|
||||
|
||||
MY_FLOAT *RtWvIn :: tick(MY_FLOAT *vector, unsigned int vectorSize)
|
||||
{
|
||||
for ( unsigned int i=0; i<vectorSize; i++ )
|
||||
vector[i] = tick();
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
const MY_FLOAT *RtWvIn :: lastFrame() const
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
const MY_FLOAT *RtWvIn :: tickFrame(void)
|
||||
{
|
||||
if ( stopped )
|
||||
start();
|
||||
|
||||
if (counter == 0) {
|
||||
try {
|
||||
audio->tickStream(stream);
|
||||
}
|
||||
catch (RtError &error) {
|
||||
handleError( error.getMessage(), StkError::AUDIO_SYSTEM );
|
||||
}
|
||||
}
|
||||
|
||||
long temp = counter * channels;
|
||||
for (unsigned int i=0; i<channels; i++)
|
||||
lastOutput[i] = data[temp++];
|
||||
|
||||
counter++;
|
||||
if (counter >= (long) bufferSize)
|
||||
counter = 0;
|
||||
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
MY_FLOAT *RtWvIn :: tickFrame(MY_FLOAT *frameVector, unsigned int frames)
|
||||
{
|
||||
return WvIn::tickFrame( frameVector, frames );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user