int sc_plugin_interface::buffer_alloc_read_channels(uint32_t index, const char * filename, uint32_t start, uint32_t frames, uint32_t channel_count, const uint32_t * channel_data) { SndfileHandle f(filename); if (!f) return -1; /* file cannot be opened */ uint32_t sf_channels = uint32_t(f.channels()); const uint32_t * max_chan = std::max_element(channel_data, channel_data + channel_count); if (*max_chan >= sf_channels) return -2; const size_t sf_frames = f.frames(); if (start > sf_frames) start = sf_frames; if (frames == 0 || frames > sf_frames - start) frames = sf_frames - start; SndBuf * buf = World_GetNRTBuf(&world, index); allocate_buffer(buf, frames, channel_count, f.samplerate()); f.seek(start, SEEK_SET); read_channel(f, channel_count, channel_data, frames, buf->data); return 0; }
int sc_plugin_interface::buffer_read(uint32_t index, const char * filename, uint32_t start_file, uint32_t frames, uint32_t start_buffer, bool leave_open) { SndBuf * buf = World_GetNRTBuf(&world, index); if (uint32_t(buf->frames) < start_buffer) return -2; /* buffer already full */ SndfileHandle sf(filename, SFM_READ); int error = buffer_read_verify(sf, start_file, buf->samplerate); if (error) return error; if (sf.channels() != buf->channels) return -3; /* sample rate or channel count mismatch */ const uint32_t buffer_remain = buf->frames - start_buffer; const uint32_t file_remain = sf.frames() - start_file; const uint32_t frames_to_read = std::min(frames, std::min(buffer_remain, file_remain)); sf.seek(start_file, SEEK_SET); sf.readf(buf->data + start_buffer*buf->channels, frames_to_read); if (leave_open) buf->sndfile = sf.takeOwnership(); return 0; }
int sc_plugin_interface::buffer_write(uint32_t index, const char * filename, const char * header_format, const char * sample_format, uint32_t start, uint32_t frames, bool leave_open) { SndBuf * buf = World_GetNRTBuf(&world, index); int format = headerFormatFromString(header_format) | sampleFormatFromString(sample_format); SndfileHandle sf(filename, SFM_WRITE, format, buf->channels, buf->samplerate); if (!sf) return -1; if (frames == 0xffffffff) frames = buf->frames; const uint32_t remain = uint32_t(buf->frames) > start ? buf->frames - start : 0; const uint32_t frames_to_write = std::min(remain, frames); if (frames_to_write) sf.writef(buf->data + start * buf->channels, frames_to_write); if (leave_open && !buf->sndfile) buf->sndfile = sf.takeOwnership(); return 0; }
int sc_plugin_interface::buffer_read_channel(uint32_t index, const char * filename, uint32_t start_file, uint32_t frames, uint32_t start_buffer, bool leave_open, uint32_t channel_count, const uint32_t * channel_data) { SndBuf * buf = World_GetNRTBuf(&world, index); if (channel_count != uint32_t(buf->channels)) return -2; /* channel count mismatch */ if (uint32_t(buf->frames) >= start_buffer) return -2; /* buffer already full */ SndfileHandle sf(filename, SFM_READ); int error = buffer_read_verify(sf, start_file, buf->samplerate); if (error) return error; uint32_t sf_channels = uint32_t(sf.channels()); const uint32_t * max_chan = std::max_element(channel_data, channel_data + channel_count); if (*max_chan >= sf_channels) return -2; const uint32_t buffer_remain = buf->frames - start_buffer; const uint32_t file_remain = sf.frames() - start_file; const uint32_t frames_to_read = std::min(frames, std::min(buffer_remain, file_remain)); sf.seek(start_file, SEEK_SET); read_channel(sf, channel_count, channel_data, frames, buf->data); if (leave_open) buf->sndfile = sf.takeOwnership(); return 0; }
bool BufAllocCmd::Stage2() { SndBuf *buf = World_GetNRTBuf(mWorld, mBufIndex); mFreeData = buf->data; bufAlloc(buf, mNumChannels, mNumFrames, mWorld->mFullRate.mSampleRate); mSndBuf = *buf; return true; }
void sc_plugin_interface::buffer_close(uint32_t index) { SndBuf * buf = World_GetNRTBuf(&world, index); if (buf->sndfile == NULL) return; sf_close(buf->sndfile); buf->sndfile = NULL; }
bool BufReadCmd::Stage2() { #ifdef NO_LIBSNDFILE SendFailure(&mReplyAddress, "/b_read", "scsynth compiled without libsndfile\n"); scprintf("scsynth compiled without libsndfile\n"); return false; #else SF_INFO fileinfo; SndBuf *buf = World_GetNRTBuf(mWorld, mBufIndex); int framesToEnd = buf->frames - mBufOffset; if (framesToEnd <= 0) return true; SNDFILE* sf = sf_open(mFilename, SFM_READ, &fileinfo); if (!sf) { char str[512]; sprintf(str, "File '%s' could not be opened: %s\n", mFilename, sf_strerror(NULL)); SendFailureWithIntValue(&mReplyAddress, "/b_read", str, mBufIndex); //SendFailure(&mReplyAddress, "/b_read", str); scprintf(str); return false; } if (fileinfo.channels != buf->channels) { char str[512]; sf_close(sf); sprintf(str, "Channel mismatch. File '%s' has %d channels. Buffer has %d channels.\n", mFilename, fileinfo.channels, buf->channels); SendFailureWithIntValue(&mReplyAddress, "/b_read", str, mBufIndex); //SendFailure(&mReplyAddress, "/b_read", str); scprintf(str); return false; } if (mFileOffset < 0) mFileOffset = 0; else if (mFileOffset > fileinfo.frames) mFileOffset = fileinfo.frames; if (mNumFrames < 0 || mNumFrames + mFileOffset > fileinfo.frames) mNumFrames = fileinfo.frames - mFileOffset; if (mNumFrames > framesToEnd) mNumFrames = framesToEnd; sf_seek(sf, mFileOffset, SEEK_SET); if (mNumFrames > 0) { sf_readf_float(sf, buf->data + (mBufOffset * buf->channels), mNumFrames); } if(buf->sndfile) sf_close(buf->sndfile); if (mLeaveFileOpen) { buf->sndfile = sf; } else { sf_close(sf); buf->sndfile = 0; } mSampleRate = (double)fileinfo.samplerate; return true; #endif }
bool BufFreeCmd::Stage2() { SndBuf *buf = World_GetNRTBuf(mWorld, mBufIndex); mFreeData = buf->data; #ifndef NO_LIBSNDFILE if (buf->sndfile) sf_close(buf->sndfile); #endif SndBuf_Init(buf); return true; }
bool BufGenCmd::Stage2() { SndBuf *buf = World_GetNRTBuf(mWorld, mBufIndex); mFreeData = buf->data; (*mBufGen->mBufGenFunc)(mWorld, buf, &mMsg); if (buf->data == mFreeData) mFreeData = NULL; mSndBuf = *buf; return true; }
sample * sc_plugin_interface::buffer_generate(uint32_t index, const char* cmd_name, struct sc_msg_iter & msg) { SndBuf * buf = World_GetNRTBuf(&world, index); sample * data = buf->data; BufGenFunc bufgen = sc_factory->find_bufgen(cmd_name); (bufgen)(&world, buf, &msg); if (data == buf->data) return NULL; else return data; }
void sc_plugin_interface::buffer_zero(uint32_t index) { SndBuf * buf = World_GetNRTBuf(&world, index); uint32_t length = buf->frames * buf->channels; uint32_t unrolled = length & ~63; uint32_t remain = length & 63; zerovec_simd(buf->data, unrolled); zerovec(buf->data + unrolled, remain); }
bool BufCloseCmd::Stage2() { #ifdef NO_LIBSNDFILE SendFailure(&mReplyAddress, "/b_close", "scsynth compiled without libsndfile\n"); scprintf("scsynth compiled without libsndfile\n"); return false; #else SndBuf *buf = World_GetNRTBuf(mWorld, mBufIndex); if (buf->sndfile) { sf_close(buf->sndfile); buf->sndfile = 0; } return true; #endif }
bool BufWriteCmd::Stage2() { #ifdef NO_LIBSNDFILE return false; #else SndBuf *buf = World_GetNRTBuf(mWorld, mBufIndex); int framesToEnd = buf->frames - mBufOffset; if (framesToEnd < 0) framesToEnd = 0; mFileInfo.samplerate = (int)buf->samplerate; mFileInfo.channels = buf->channels; SNDFILE* sf = sf_open(mFilename, SFM_WRITE, &mFileInfo); if (!sf) { char str[512]; sprintf(str, "File '%s' could not be opened: %s\n", mFilename, sf_strerror(NULL)); SendFailureWithIntValue(&mReplyAddress, "/b_write", str, mBufIndex); //SendFailure(&mReplyAddress, "/b_write", str); scprintf(str); return false; } if (mNumFrames < 0 || mNumFrames > buf->frames) mNumFrames = buf->frames; if (mNumFrames > framesToEnd) mNumFrames = framesToEnd; sf_command(sf, SFC_SET_CLIPPING, NULL, SF_TRUE); // choose clipping rather than wraparound for integer-format files if (mNumFrames > 0) { sf_writef_float(sf, buf->data + (mBufOffset * buf->channels), mNumFrames); } if(buf->sndfile) sf_close(buf->sndfile); if (mLeaveFileOpen) { buf->sndfile = sf; } else { sf_close(sf); buf->sndfile = 0; } return true; #endif }
int sc_plugin_interface::buffer_read_alloc(uint32_t index, const char * filename, uint32_t start, uint32_t frames) { SndfileHandle f(filename); if (!f) return -1; /* file cannot be opened */ const size_t sf_frames = f.frames(); if (start > sf_frames) start = sf_frames; if (frames == 0 || frames > sf_frames - start) frames = sf_frames - start; SndBuf * buf = World_GetNRTBuf(&world, index); allocate_buffer(buf, frames, f.channels(), f.samplerate()); f.seek(start, SEEK_SET); f.readf(buf->data, frames); return 0; }
bool BufAllocReadCmd::Stage2() { #ifdef NO_LIBSNDFILE SendFailure(&mReplyAddress, "/b_allocRead", "scsynth compiled without libsndfile\n"); scprintf("scsynth compiled without libsndfile\n"); return false; #else SndBuf *buf = World_GetNRTBuf(mWorld, mBufIndex); SF_INFO fileinfo; memset(&fileinfo, 0, sizeof(fileinfo)); SNDFILE* sf = sf_open(mFilename, SFM_READ, &fileinfo); if (!sf) { char str[512]; sprintf(str, "File '%s' could not be opened: %s\n", mFilename, sf_strerror(NULL)); SendFailureWithIntValue(&mReplyAddress, "/b_allocRead", str, mBufIndex); //SendFailure(&mReplyAddress, "/b_allocRead", str); scprintf(str); return false; } if (mFileOffset < 0) mFileOffset = 0; else if (mFileOffset > fileinfo.frames) mFileOffset = fileinfo.frames; if (mNumFrames <= 0 || mNumFrames + mFileOffset > fileinfo.frames) mNumFrames = fileinfo.frames - mFileOffset; // alloc data size mFreeData = buf->data; SCErr err = bufAlloc(buf, fileinfo.channels, mNumFrames, fileinfo.samplerate); if (err) goto leave; sf_seek(sf, mFileOffset, SEEK_SET); sf_readf_float(sf, buf->data, mNumFrames); leave: mSndBuf = *buf; sf_close(sf); return true; #endif }
bool BufAllocReadChannelCmd::Stage2() { #ifdef NO_LIBSNDFILE SendFailure(&mReplyAddress, "/b_allocReadChannel", "scsynth compiled without libsndfile\n"); scprintf("scsynth compiled without libsndfile\n"); return false; #else SndBuf *buf = World_GetNRTBuf(mWorld, mBufIndex); SF_INFO fileinfo; memset(&fileinfo, 0, sizeof(fileinfo)); SNDFILE* sf = sf_open(mFilename, SFM_READ, &fileinfo); if (!sf) { char str[512]; sprintf(str, "File '%s' could not be opened: %s\n", mFilename, sf_strerror(NULL)); SendFailureWithIntValue(&mReplyAddress, "/b_allocReadChannel", str, mBufIndex); //SendFailure(&mReplyAddress, "/b_allocRead", str); scprintf(str); return false; } if (mFileOffset < 0) mFileOffset = 0; else if (mFileOffset > fileinfo.frames) mFileOffset = fileinfo.frames; if (mNumFrames <= 0 || mNumFrames + mFileOffset > fileinfo.frames) mNumFrames = fileinfo.frames - mFileOffset; if (mNumChannels == 0) { // alloc data size mFreeData = buf->data; SCErr err = bufAlloc(buf, fileinfo.channels, mNumFrames, fileinfo.samplerate); if (err) goto leave; // read all channels sf_seek(sf, mFileOffset, SEEK_SET); sf_readf_float(sf, buf->data, mNumFrames); } else { // verify channel indexes if (!CheckChannels(fileinfo.channels)) { const char* str = "Channel index out of range.\n"; SendFailureWithIntValue(&mReplyAddress, "/b_allocReadChannel", str, mBufIndex); //SendFailure(&mReplyAddress, "/b_allocRead", str); scprintf(str); sf_close(sf); return false; } // alloc data size mFreeData = buf->data; SCErr err = bufAlloc(buf, mNumChannels, mNumFrames, fileinfo.samplerate); if (err) goto leave; // alloc temp buffer float* data = (float*)malloc(mNumFrames*fileinfo.channels*sizeof(float)); if (data == 0) goto leave; // read some channels sf_seek(sf, mFileOffset, SEEK_SET); sf_readf_float(sf, data, mNumFrames); CopyChannels(buf->data, data, fileinfo.channels, mNumFrames); // free temp buffer free(data); } leave: mSndBuf = *buf; sf_close(sf); return true; #endif }
bool BufZeroCmd::Stage2() { SndBuf *buf = World_GetNRTBuf(mWorld, mBufIndex); memset(buf->data, 0, buf->samples * sizeof(float)); return true; }
SndBuf * sc_plugin_interface::allocate_buffer(uint32_t index, uint32_t frames, uint32_t channels) { SndBuf * buf = World_GetNRTBuf(&world, index); allocate_buffer(buf, frames, channels, world.mFullRate.mSampleRate); return buf; }
bool BufReadChannelCmd::Stage2() { #ifdef NO_LIBSNDFILE SendFailure(&mReplyAddress, "/b_readChannel", "scsynth compiled without libsndfile\n"); scprintf("scsynth compiled without libsndfile\n"); return false; #else SF_INFO fileinfo; SndBuf *buf = World_GetNRTBuf(mWorld, mBufIndex); int framesToEnd = buf->frames - mBufOffset; if (framesToEnd <= 0) return true; SNDFILE* sf = sf_open(mFilename, SFM_READ, &fileinfo); if (!sf) { char str[512]; sprintf(str, "File '%s' could not be opened: %s\n", mFilename, sf_strerror(NULL)); SendFailureWithIntValue(&mReplyAddress, "/b_readChannel", str, mBufIndex); //SendFailure(&mReplyAddress, "/b_read", str); scprintf(str); return false; } if (mNumChannels > 0) { // verify channel indexes if (!( CheckChannels(fileinfo.channels)) ) { // nescivi: && CheckChannels(buf->channels) (should not check here for buf->channels) const char* str = "Channel index out of range.\n"; SendFailureWithIntValue(&mReplyAddress, "/b_readChannel", str, mBufIndex); //SendFailure(&mReplyAddress, "/b_allocRead", str); scprintf(str); sf_close(sf); return false; } // nescivi: this also seems out of place: we want to read from a file with more channels than are in the buffer // } else if (fileinfo.channels != buf->channels) { // char str[256]; // sf_close(sf); // sprintf(str, "Channel mismatch. File '%s' has %d channels. Buffer has %d channels.\n", // mFilename, fileinfo.channels, buf->channels); // SendFailure(&mReplyAddress, "/b_read", str); // scprintf(str); // return false; } if (mFileOffset < 0) mFileOffset = 0; else if (mFileOffset > fileinfo.frames) mFileOffset = fileinfo.frames; if (mNumFrames < 0 || mNumFrames + mFileOffset > fileinfo.frames) mNumFrames = fileinfo.frames - mFileOffset; if (mNumFrames > framesToEnd) mNumFrames = framesToEnd; sf_seek(sf, mFileOffset, SEEK_SET); if (mNumFrames > 0) { if (mNumChannels == 0) { // read all channels sf_readf_float(sf, buf->data + (mBufOffset * buf->channels), mNumFrames); } else { // alloc temp buffer float* data = (float*)malloc(mNumFrames*fileinfo.channels*sizeof(float)); if (data == 0) goto leave; // read some channels sf_seek(sf, mFileOffset, SEEK_SET); sf_readf_float(sf, data, mNumFrames); CopyChannels(buf->data + (mBufOffset * mNumChannels), data, fileinfo.channels, mNumFrames); // free temp buffer free(data); } } leave: if(buf->sndfile) sf_close(buf->sndfile); if (mLeaveFileOpen) { buf->sndfile = sf; } else { sf_close(sf); buf->sndfile = 0; } mSampleRate = (double)fileinfo.samplerate; return true; #endif }