Delay between gui and sound

I’m creating an interactive ocilator,

by clicking on the bar
1-Create a sine wave in samples [] of “n_samples_wave” samples
2-then a thread reads sample by sample and passes it to audiodata [0]
3-sourcedataline writes audiodata samples sound card [0]

The problem is that pressing the bar takes a few milliseconds to hear the new frequency.

I want the frequency to change and be heard quickly as in http://www.szynalski.com/tone-generator/


float n_samples_wave=360;


float[] samples = new float[44100];//buffer of samples 

import javax.sound.sampled.*;


//create thread for write samples in sound card
RunnableDemo R1 = new RunnableDemo( "Thread-1");
      
        

  AudioFormat audioFormat;

  SourceDataLine sourceDataLine;



byte audioData[] = new byte [44100];
float f=1;



HScrollbar hs1;

 int sam=1;
 
 
 
 
 
 
 
 
 
void setup()
{
  size(370, 360, P3D);
   hs1 = new HScrollbar(0, height/2-8, width, 12, 16);
  loadPixels();  





playAudio();

R1.start();

  updatePixels(); 
   background(0);
}







void draw()
{

loadPixels();
//refresh screen
for(int yy=0 ; yy<180; yy++){
for(int xx=0 ; xx<width ;xx++){
 setpixel(xx,yy,0);

}
}




// scrollbar to create wave
   if (hs1.locked){ //if you press the scrollbar


   f=hs1.getPos()/35;
   n_samples_wave=44100/(122.5*f);//44100/360=122.5
   //frequency 122.5 is formed by 360 samples
   //frequency 1 is formed by 44100 samples
   
   
  // create wave with "n_samples_wave" samples.
         for(int i=0; i<n_samples_wave; i++){
samples[i]=20*sin(radians(i)*f);
         }

   }





// if (keyPressed && key=='z'){ 

//}












//show waveform
for(int i = 0; i < 359; i++)
  {
   // if (i==477){ stroke(255,0,0);}
   stroke(255);
//if (i==1){thread("sine") ;};
    line( i, 50  - samples[i],  i+1, 50  - samples[i+1] );

  }
  
  //show buffer
    line( 0, 50 , width, 50 );
    stroke(255,255,0);
line(0,90,n_samples_wave,90);
line(n_samples_wave,50,n_samples_wave,90);
//line(0,240,width,240);




 
 updatePixels();



 // //n_samples_wave=44100/(122.5*1) freq 122.5=360 samples



 
 hs1.update();

  hs1.display(); 
 
 fill(255);
 
 

}//end draw
















  private AudioFormat getAudioFormat(){
    float samplerate = 44100.0F;
    //8000,11025,16000,22050,44100
    int sampleSizeInBits =8;
    //8,16
    int channels = 1;
    //1,2
    boolean signed = true;
    //true,false
    boolean bigEndian = true;
    //true,false
    return new AudioFormat(
                      samplerate,
                      sampleSizeInBits,
                      channels,
                      signed,
                      bigEndian);
  }//end getAudioFormat









  private void playAudio() {
    try{

      AudioFormat audioFormat = getAudioFormat();
 
     
      DataLine.Info dataLineInfo =  new DataLine.Info( SourceDataLine.class, audioFormat);
      sourceDataLine = (SourceDataLine)
      AudioSystem.getLine(dataLineInfo);
      sourceDataLine.open(audioFormat);
      sourceDataLine.start();


      } catch (LineUnavailableException ev) {
          
     
    }//end catch
  }//end playAudio












class RunnableDemo implements Runnable {
   private Thread t;
   private String threadName;
   
   RunnableDemo( String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {

// thread will be constantly receiving the values of samples []
// "n_samples_wave" sample samples will be read [] and "n_samples_wave" samples will be written to the sound card each while
      
while(true){  

      for(int i=0; i<n_samples_wave; i+=1){
   if ((map(samples[i],0,20,0,100))<127  && (map(samples[i],0,20,0,100))>-127 ) { 
     
   audioData[0]=byte (map(samples[i],0,20,0,100));
 }
 
// samples can only have values from -127 to 127
 
   if ((map(samples[i],0,20,0,100))>127  ) { // if the current sample has a value greater than 127
     
   audioData[0]=byte (127);
 } 
   if ((map(samples[i],0,20,0,100))<-127  ) { 
     
   audioData[0]=byte (-127);
 }  
 
 

sourceDataLine.write( audioData, 0,1);


}
 
 
}

}//run()
   
   public void start () {
    
      if (t == null) {
         t = new Thread (this, threadName);
         t.start ();
      }
      
     
   }

   
}//end class










void setpixel( int x, int y , color col)
{
pixels[x+width*y]=color(col);
}


int getpixel(PGraphics arr, int x, int y )
{
return int(arr.pixels[x+arr.width*y]);
}

int getpixel( int x, int y )
{
return int(pixels[x+width*y]);
}

int getpixel(PImage arr, int x, int y )
{
return int(arr.pixels[x+arr.width*y]);
}
1 Like

I highly recommend using an audio library like Minim or Beads, or if you want to go lower level try the JAudioLibs audio servers which Beads uses.

At the very least, use the version of open() on the SDL that specifies a buffer size.

1 Like