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;
}
Example #10
0
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
}