diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/mossrose.c | 101 | 
2 files changed, 101 insertions, 1 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cca9610..0453c34 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,6 +3,7 @@ project(mossrose)  target_sources(mossrose PUBLIC  	${CMAKE_CURRENT_LIST_DIR}/mossrose.c  	${CMAKE_CURRENT_LIST_DIR}/channel.c +	${CMAKE_CURRENT_LIST_DIR}/sound.c  ) diff --git a/src/mossrose.c b/src/mossrose.c index 4babfd7..fb017cd 100644 --- a/src/mossrose.c +++ b/src/mossrose.c @@ -13,26 +13,125 @@ struct mossrose_global_t {  } mossrose_global; +static int callback( +	const void *input, +	void *output, +	unsigned long frame_count, +	const PaStreamCallbackTimeInfo* time_info, +	PaStreamCallbackFlags status_flags, +	void *user_data) +{ +	float *out = output; +	float *left, *right; +	float l, r; +	 +	for (int i=0; i<frame_count; i++) { +		left = out + 2*i; +		right = left + 1; +		*left = 0; +		*right = 0; +		for (int j=0; j<mossrose_global.n_channels; j++) { +			struct channel_t *chan = mossrose_global.channels + j; +			channel_get_next_sample(&l, &r, chan); +			*left += l; +			*right += r; +		} +	} +	return 0; +} + +  int mossrose_init(double sample_rate, int n_channels, bool init_plibsys)  { +	/* optionally initialze plibsys */ +	if (init_plibsys) +		p_libsys_init(); +  	/* initialize channels */  	mossrose_global.n_channels = n_channels;  	mossrose_global.channels = malloc(n_channels * sizeof(struct channel_t));  	if (mossrose_global.channels == NULL) { -		fprintf("failed to allocate memory for %d channels\n", n_channels); +		fprintf(stderr, "failed to allocate memory for %d channels\n", n_channels);  		return 1;  	}  	for (int i=0; i<n_channels; i++)  		channel_init(mossrose_global.channels + i); +	PaError err; +	/* initialize portaudio */ +	err = Pa_Initialize(); +	if (err != paNoError) { +		fprintf(stderr, "failed to initialize portaudio\n"); +		return 2; +	} + +	/* initialize stream */ +	err = Pa_OpenDefaultStream(&(mossrose_global.stream), 0, 2, paFloat32, sample_rate, 0, callback, NULL); +	if (err != paNoError) { +		fprintf(stderr, "failed to open audio stream!\n"); +		return 3; +	} + + +	/* start stream */ +	err = Pa_StartStream(mossrose_global.stream); +	if (err != paNoError) { +		fprintf(stderr, "failed to start audio stream\n"); +		return 4; +	} + +	return 0;  };  int mossrose_play(struct mossrose_sound_t *sound, int channel)  { +	if (channel >= 0) { +		/* play on specified channel */ +		if (channel_sound_load(mossrose_global.channels + channel, sound, true) == 0) +			return channel; +		else +			return -1; +	} +	else { +		/* play on first available channel */ +		for (int i=0; i<mossrose_global.n_channels; i++) { +			struct channel_t *chan = mossrose_global.channels + i; +			if (channel_sound_load(chan, sound, false) == 0) return i; +		} +		return -1; +	} +} + + +void mossrose_channel_set_volume(int channel, float volume) { +	struct channel_t *chan = mossrose_global.channels + channel; +	channel_set_volume(chan, volume); +} + + +void mossrose_channel_set_pan(int channel, float left, float right) { +	struct channel_t *chan = mossrose_global.channels + channel; +	channel_set_pan(chan, left, right); +} + + +void mossrose_channel_pause(int channel) { +	struct channel_t *chan = mossrose_global.channels + channel; +	channel_pause(chan); +} + + +void mossrose_channel_resume(int channel) { +	struct channel_t *chan = mossrose_global.channels + channel; +	channel_resume(chan);  }  int mossrose_terminate()  { +	Pa_AbortStream(mossrose_global.stream); +	Pa_CloseStream(mossrose_global.stream); +	Pa_Terminate(); +	return 0;  }  | 
