commit 1506db6b4399526fad6c95caa1e79c6c74919a34
parent 3b3d09183fa22af5e1a41ebbe9e6f00fea6c84c7
Author: paulnasca <paulnasca>
Date: Wed, 17 Dec 2003 16:10:16 +0000
*** empty log message ***
Diffstat:
1 file changed, 196 insertions(+), 0 deletions(-)
diff --git a/src/Output/JACK_RTaudiooutput.C b/src/Output/JACK_RTaudiooutput.C
@@ -0,0 +1,196 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ JACKaudiooutput.C - Audio output for JACK
+ Copyright (C) 2002 Nasca Octavian Paul
+ Author: Nasca Octavian Paul
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+
+
+extern "C" {
+#include <jack/ringbuffer.h>
+};
+#include "JACKaudiooutput.h"
+
+Master *jackmaster;
+jack_client_t *jackclient;
+jack_port_t *outport_left,*outport_right;
+jack_ringbuffer_t *rb=NULL;
+
+REALTYPE *jackoutl,*jackoutr;
+int jackfinish=0;
+
+void *thread_blocked(void *arg);
+int jackprocess(jack_nframes_t nframes,void *arg);
+int jacksrate(jack_nframes_t nframes,void *arg);
+void jackshutdown(void *arg);
+
+pthread_cond_t more_data=PTHREAD_COND_INITIALIZER;
+pthread_mutex_t zyn_thread_lock=PTHREAD_MUTEX_INITIALIZER;
+
+pthread_t bthr;
+
+
+void JACKaudiooutputinit(Master *master_){
+ jackmaster=master_;
+ jackclient=0;
+ char tmpstr[100];
+
+ jackoutl=new REALTYPE [SOUND_BUFFER_SIZE];
+ jackoutr=new REALTYPE [SOUND_BUFFER_SIZE];
+
+ int rbbufsize=SOUND_BUFFER_SIZE*sizeof (REALTYPE)*2*2;
+ printf("%d\n",rbbufsize);
+ rb=jack_ringbuffer_create(rbbufsize);
+ memset(rb->buf,rbbufsize,0);
+
+
+ for (int i=0;i<15;i++){
+ if (i!=0) snprintf(tmpstr,100,"ZynAddSubFX_%d",i);
+ else snprintf(tmpstr,100,"ZynAddSubFX");
+ jackclient=jack_client_new(tmpstr);
+ if (jackclient!=0) break;
+ };
+
+ if (jackclient==0) {
+ fprintf(stderr,"\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n\n\n");
+ exit(1);
+ };
+
+ fprintf(stderr,"Internal SampleRate = %d\nJack Output SampleRate= %d\n",SAMPLE_RATE,jack_get_sample_rate(jackclient));
+ if ((unsigned int)jack_get_sample_rate(jackclient)!=(unsigned int) SAMPLE_RATE)
+ fprintf(stderr,"It is recomanded that the both samplerates to be equal.\n");
+
+ jack_set_process_callback(jackclient,jackprocess,0);
+ jack_set_sample_rate_callback(jackclient,jacksrate,0);
+ jack_on_shutdown(jackclient,jackshutdown,0);
+
+ outport_left=jack_port_register(jackclient,"out_1",
+ JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0);
+ outport_right=jack_port_register(jackclient,"out_2",
+ JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0);
+
+ if (jack_activate(jackclient)){
+ fprintf(stderr,"Cannot activate jack client\n");
+ exit(1);
+ };
+
+ pthread_create(&bthr,NULL,thread_blocked,NULL);
+
+ /*
+ jack_connect(jackclient,jack_port_name(outport_left),"alsa_pcm:out_1");
+ jack_connect(jackclient,jack_port_name(outport_right),"alsa_pcm:out_2");
+ */
+};
+
+void *thread_blocked(void *arg){
+ int datasize=SOUND_BUFFER_SIZE*sizeof (REALTYPE);
+
+ //try to get realtime
+ sched_param sc;
+ sc.sched_priority=50;
+ int err=sched_setscheduler(0,SCHED_FIFO,&sc);
+
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
+ pthread_mutex_lock(&zyn_thread_lock);
+
+ while (jackfinish==0){
+ while (jack_ringbuffer_write_space(rb)>=datasize){
+ pthread_mutex_lock(&jackmaster->mutex);
+ jackmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE,jack_get_sample_rate(jackclient),jackoutl,jackoutr);
+ pthread_mutex_unlock(&jackmaster->mutex);
+
+ jack_ringbuffer_write(rb, (char *) jackoutl,datasize);
+ jack_ringbuffer_write(rb, (char *) jackoutr,datasize);
+ };
+ pthread_cond_wait(&more_data,&zyn_thread_lock);
+ };
+ pthread_mutex_unlock(&zyn_thread_lock);
+
+ return(0);
+};
+
+
+int jackprocess(jack_nframes_t nframes,void *arg){
+ jack_default_audio_sample_t *outl=(jack_default_audio_sample_t *) jack_port_get_buffer (outport_left, nframes);
+ jack_default_audio_sample_t *outr=(jack_default_audio_sample_t *) jack_port_get_buffer (outport_right, nframes);
+
+ int datasize=nframes*sizeof (REALTYPE);
+ int incoming_datasize=SOUND_BUFFER_SIZE*sizeof (REALTYPE);
+ int data_read=0;
+
+
+ if (jack_ringbuffer_read_space(rb)>=(2*incoming_datasize)){
+ if (datasize>incoming_datasize){
+ data_read=0;
+ while (data_read < datasize){
+ jack_ringbuffer_read(rb, (char *) outl+data_read,datasize);
+ jack_ringbuffer_read(rb, (char *) outr+data_read,datasize);
+ data_read+=incoming_datasize;
+ };
+ } else if (datasize==incoming_datasize){
+ jack_ringbuffer_read(rb, (char *) outl,datasize);
+ jack_ringbuffer_read(rb, (char *) outr,datasize);
+ } else {
+ };
+ } else {//the ringbuffer is empty or there are too small amount of samples in it
+ for (int i=0;i<nframes;i++){
+ outl[i]=0.0;outr[i]=0.0;
+ };
+ };
+/* if (jack_ringbuffer_read_space(rb)>=datasize){
+ jack_ringbuffer_read(rb, (char *) outl,datasize);
+ jack_ringbuffer_read(rb, (char *) outr,datasize);
+ } else {//the ringbuffer is empty or there are too small amount of samples in it
+ for (int i=0;i<nframes;i++){
+ outl[i]=0.0;outr[i]=0.0;
+ };
+ };
+*/
+ if (pthread_mutex_trylock(&zyn_thread_lock)==0){
+ pthread_cond_signal(&more_data);
+ pthread_mutex_unlock(&zyn_thread_lock);
+ };
+
+ return(0);
+};
+
+void JACKfinish(){
+ jackfinish=1;
+ jack_ringbuffer_free(rb);
+ jack_client_close(jackclient);
+
+ usleep(100000);
+ delete(jackoutl);
+ delete(jackoutr);
+};
+
+int jacksrate(jack_nframes_t nframes,void *arg){
+
+ return(0);
+};
+
+void jackshutdown(void *arg){
+};
+
+
+