I'm trying to use the STK from Stanford to do some realtime wavetable synthesis. I'm using the FMVoices instrument class https://ccrma.stanford.edu/software/stk/classstk_1_1FMVoices.html and trying to use it in a callback routine defined below.
int tick( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status, void *dataPointer )
{
FMVoices *FM = (FMVoices *) dataPointer;
register StkFloat *samples = (StkFloat *) outputBuffer;
for ( unsigned int i=0; i<nBufferFrames; i++ )
*samples++ = FM->tick();
return 0;
}
The issue, I think, is with the type of that last parameter. I'm getting a runtime error : "0xC0000005: Access violation executing location 0x000000001." Now, this is the way that the callback is supposed to be written for other STK instruments like Clarinet or even the FileLoop class, but there's something funky about FMVoices. The object is passed to openStream (which handles platform specific realtime output) as a pointer to void. The callback is called automatically when the system's audio buffer is full. A code snippet that implements this and DOES work for other instruments is shown below:
int main()
{
// Set the global sample rate before creating class instances.
Stk::setSampleRate( 44100.0 );
RtAudio dac;
Instrmnt * instrument_FM;
int nFrames = 10000;
try {
instrument_FM = new FMVoices;
}
catch ( StkError & ) {
goto cleanup;
}
instrument_FM->setFrequency(440.0);
// Figure out how many bytes in an StkFloat and setup the RtAudio stream.
RtAudio::StreamParameters parameters;
parameters.deviceId = dac.getDefaultOutputDevice();
parameters.nChannels = 1;
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
unsigned int bufferFrames = RT_BUFFER_SIZE;
try {
dac.openStream( ¶meters, NULL, format, (unsigned int)Stk::sampleRate(), &bufferFrames, &tick, (void *)&instrument_FM);
}
catch ( RtError &error ) {
error.printMessage();
Sleep(1000);
goto cleanup;
}
The size of nFrames does not seem to have an effect. It just seemed to me that these types of errors usually come from referencing a pointer to void.
The problem is you are taking the address of a pointer, and passing it into openStream
.
// pointer to instrument
Instrmnt * instrument_FM;
// snip ...
// &instrument_FM is a pointer to a pointer! i.e. Instrmnt **
dac.openStream( ¶meters, /* other params */, (void *)&instrument_FM)
The quickest solution is to just get rid of the &
in that line.
Now some comments on C++, and some more fixes to your code. The code looks like a mixture of C and Java, and opens up a lot of pitfalls to fall into, one of which led to your problem.
FMVoices
. Use the stack just like you did for RtAudio dac
.
delete
ing the memory you allocated FMVoices instrument_FM;
try
/ catch
in most cases for cleanup since C++ has destructors that trigger at the end of scope, and propagate the error.
delete
and having cleanup operations goto
in C++, it's really not needed. (unlike in C, where it could be used for cleanup).
static_cast<>
and reinterpret_cast<>
, instead of C-style casts
Here's the revised code:
int main()
{
// Set the global sample rate before creating class instances.
Stk::setSampleRate( 44100.0 );
RtAudio dac;
FMVoices instrument_FM;
instrument_FM.setFrequency(440.0);
// Figure out how many bytes in an StkFloat and setup the RtAudio stream.
RtAudio::StreamParameters parameters;
parameters.deviceId = dac.getDefaultOutputDevice();
parameters.nChannels = 1;
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
unsigned int bufferFrames = RT_BUFFER_SIZE;
// didn't get rid of this try since you want to print the error message.
try {
// note here i need the ampersand &, because instrument_FM is on the stack
dac.openStream( ¶meters, NULL, format, static_cast<unsigned int>(Stk::sampleRate()), &bufferFrames, &tick, reinterpret_cast<void*>(&instrument_FM));
}
catch ( RtError& error ) {
error.printMessage();
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.