// scpipe.cpp : Defines the entry point for the console application. // #include #include #include #include #import #include "SCCore.h" // #define LOG_EXCHANGE enum { BUFFER_SIZE = 4096 }; static NSFileHandle *pipe_in = nil; static NSFileHandle *pipe_out = nil; void put_bytes( const void * out, uint32_t size ) { @autoreleasepool { NSError *error; NSData *data = [NSData dataWithBytes:out length:size]; [pipe_out writeData:data error:&error]; } } void put_code( uint32_t code ) { put_bytes( &code, sizeof(code) ); } void get_bytes( void * in, uint32_t size ) { NSUInteger bytesDone; @autoreleasepool { NSError *error = nil; NSData *data = [pipe_in readDataUpToLength:size error:&error]; if(!data || error) { memset( in, 0, size ); return; } bytesDone = [data length]; memcpy(in, [data bytes], bytesDone); } if(bytesDone < size) { memset(((uint8_t *)in) + bytesDone, 0, size - bytesDone); } } uint32_t get_code() { uint32_t code; get_bytes( &code, sizeof(code) ); return code; } int main( int argc, const char * argv[] ) { if ( argv == NULL || argc != 2 ) return 1; unsigned code = 0; SCCore * sampler = NULL; uint32_t sample_rate = 44100; std::vector sample_buffer; unsigned int samples_buffered = 0; uint8_t* msgbuf = NULL; size_t msgsize = 0; pipe_in = [NSFileHandle fileHandleWithStandardInput]; pipe_out = [NSFileHandle fileHandleWithStandardOutput]; sampler = new SCCore; if ( !sampler->Load( argv[ 1 ] ) ) { code = 1; goto exit; } if (sampler->TG_initialize(0) < 0) { code = 2; goto exit; } sample_buffer.resize( BUFFER_SIZE * 4 ); put_code( 0 ); for (;;) { uint32_t command = get_code(); if ( !command ) break; switch ( command ) { case 1: // Set Sample Rate { uint32_t size = get_code(); if ( size != sizeof(sample_rate) ) { code = 10; goto exit; } sample_rate = get_code(); sampler->TG_activate(44100.0, 1024); sampler->TG_setMaxBlockSize(256); sampler->TG_setSampleRate((float)sample_rate); sampler->TG_setSampleRate((float)sample_rate); sampler->TG_setMaxBlockSize(BUFFER_SIZE); put_code( 0 ); } break; case 2: // Send MIDI Event { uint32_t b = get_code(); sampler->TG_ShortMidiIn(b, 0); put_code( 0 ); } break; case 3: // Send System Exclusive Event { uint32_t size = get_code(); if (size + 1 > msgsize) { msgsize = (size + 1024) & ~1023; msgbuf = (uint8_t *) realloc(msgbuf, msgsize); } if (!msgbuf) { code = 3; goto exit; } get_bytes( msgbuf, size ); if ( msgbuf[size-1] != 0xF7 ) msgbuf[size] = 0xF7; sampler->TG_LongMidiIn( msgbuf, 0 ); put_code( 0 ); } break; case 4: // Render Samples { uint32_t count = get_code(); put_code( 0 ); while( count ) { unsigned count_to_do = MIN(count, BUFFER_SIZE); memset(&sample_buffer[0], 0, count_to_do * sizeof(float)); memset(&sample_buffer[BUFFER_SIZE], 0, count_to_do * sizeof(float)); sampler->TG_setInterruptThreadIdAtThisTime(); sampler->TG_Process(&sample_buffer[0], &sample_buffer[BUFFER_SIZE], count_to_do); float * out = &sample_buffer[BUFFER_SIZE * 2]; for ( unsigned i = 0; i < count_to_do; ++i ) { float sample = sample_buffer[i]; out[ 0 ] = sample; sample = sample_buffer[BUFFER_SIZE + i]; out[ 1 ] = sample; out += 2; } put_bytes( &sample_buffer[BUFFER_SIZE * 2], count_to_do * sizeof(float) * 2 ); count -= count_to_do; } } break; case 5: // Junk Samples { uint32_t count = get_code(); while ( count ) { unsigned count_to_do = MIN(count, BUFFER_SIZE); sampler->TG_setInterruptThreadIdAtThisTime(); sampler->TG_Process(&sample_buffer[0], &sample_buffer[BUFFER_SIZE], count_to_do); count -= count_to_do; } put_code( 0 ); } break; case 6: // Send event, with timestamp { uint32_t b = get_code(); uint32_t timestamp = get_code(); sampler->TG_ShortMidiIn(b, timestamp); put_code( 0 ); } break; case 7: // Send System Exclusive, with timestamp { uint32_t size = get_code(); uint32_t timestamp = get_code(); if (size + 1 > msgsize) { msgsize = (size + 1024) & ~1023; msgbuf = (uint8_t*)realloc(msgbuf, msgsize); } if (!msgbuf) { code = 3; goto exit; } get_bytes(msgbuf, size); if (msgbuf[size - 1] != 0xF7) msgbuf[size] = 0xF7; sampler->TG_LongMidiIn(msgbuf, timestamp); put_code(0); } break; default: code = 4; goto exit; break; } } exit: delete sampler; put_code( code ); return code; }