Bonjour à tous

Voilà, je fait des essais de création sonore avec le programme ci-dessous.

A la ligne 84, vous pouvez voir une constante nommée "BUFFER_DURATION". J'ai l'impression que cette dernière détermine la durée d'un morceau de son avant qu'il ne soit repris en boucle pour créer un son continu en sortie (j'explique avec mes mots et selon ce que je comprends du programme, merci de me reprendre si je ne suis pas correct).
Mon problème est que si je met cette valeur en dessous de 0.426, le son s'arrête au bout d'un temps court (je dirais 426 millisecondes .... par rapport à la valeur de BUFFER_DURATION). Et au-dessus de 0.425, le son sera continu. Je remarque aussi que plus la valeur de BUFFER_DURATION est petite (en dessous de 0.426), plus le son sera court.

J'aimerai avoir une réponse plus rapide (en fait un retard faible) avec le slider et donc je pense que le mieux serait d'avoir cette BUFFER_DURATION la plus petite possible.
Par "réponse plus rapide avec le slider", je veux dire que, lorsque je bouge le slider, j'aimerai que le son soit modifié le plus rapidement possible. Or, même en mettant le BUFFER_DURATION à 0.426 (valeur la plus petite possible chez moi pour que le son soit lu en boucle) je ne suis pas satisfait de la réponse.

Autre question : Y-a-t'il un lien entre les réglages de la JavaVirtualMachine et le BUFFER_DURATION ou la continuité du son en sortie ?

Merci pour votre aide !

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.nio.ByteBuffer;
 
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
 
 
public class JFrame_sliderSine extends JFrame {
 
	/**
         * 
         */
	private static final long serialVersionUID = 3481827887325136254L;
 
	private SampleThread m_thread;
	private JSlider m_sliderPitch;
 
	//Launch the app
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					JFrame_sliderSine frame = new JFrame_sliderSine();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}
 
	public JFrame_sliderSine() {
		//UI stuff, created with WindowsBuilder
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				m_thread.exit();
				System.exit(0);
			}
		});
 
		setTitle("Slider Frequency Sine Wave Demo");
		setResizable(false);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 793, 166);
		setLocationRelativeTo(null);
		getContentPane().setLayout(new BorderLayout(0, 0));
 
		m_sliderPitch = new JSlider();
		m_sliderPitch.setName("");
		m_sliderPitch.setMinimum(100);
		m_sliderPitch.setPaintLabels(true);
		m_sliderPitch.setPaintTicks(true);
		m_sliderPitch.setMajorTickSpacing(500);
		m_sliderPitch.setMinorTickSpacing(100);
		m_sliderPitch.setMaximum(4100);
		m_sliderPitch.setValue(880);
		getContentPane().add(m_sliderPitch);
 
		JLabel lblAdjustPitch = new JLabel("Adjust pitch");
		lblAdjustPitch.setHorizontalAlignment(SwingConstants.CENTER);
		lblAdjustPitch.setFont(new Font("Tahoma", Font.PLAIN, 18));
		getContentPane().add(lblAdjustPitch, BorderLayout.NORTH);
 
		//Non-UI stuff
		m_thread = new SampleThread();
		m_thread.start();
	}
 
	class SampleThread extends Thread{
		final static public int SAMPLING_RATE = 44100;
		final static public int SAMPLE_SIZE = 2;			//Sample size in bytes
		final static public double BUFFER_DURATION = 0.426;	//About a 500ms buffer
 
		//You can play with the size of this buffer if you want.  Making it smaller speeds up
	    //the response to the slider movement, but if you make it too small you will get 
	    //noise in your output from buffer underflows, etc...
 
		// Size in bytes of sine wave samples we'll create on each loop pass 
		final static public int SINE_PACKET_SIZE = (int)(BUFFER_DURATION * SAMPLING_RATE * SAMPLE_SIZE);
 
		SourceDataLine line; //$
		public double fFreq;
		public boolean bExitThread = false;
 
		//Get the number of queued samples in the SourceDataLine buffer
		private int getLineSampleCount() {
			return line.getBufferSize() - line.available();
		}
 
		//Continually fill the audio output buffer whenever it starts to get empty, SINE_PACKET_SIZE/2
	    //samples at a time, until we tell the thread to exit
		public void run() {
			//Position through the sine wave as a percentage (i.e. 0-1 is 0-2*PI)
			double fCyclePosition = 0;
 
			//Open up the audio output, using a sampling rate of 44100hz, 16 bit samples, mono, and big 
	        // endian byte ordering.   Ask for a buffer size of at least 2*SINE_PACKET_SIZE
			try {
				AudioFormat format = new AudioFormat(44100, 16, 1, true, true);
				DataLine.Info info = new DataLine.Info(SourceDataLine.class, format, SINE_PACKET_SIZE * 2);
 
				if(!AudioSystem.isLineSupported(info)) throw new LineUnavailableException();
 
				line = (SourceDataLine)AudioSystem.getLine(info);
				line.open(format);
				line.start();
			} catch (LineUnavailableException e){
				System.out.println("Line of that type is not available");
				e.printStackTrace();
				System.exit(-1);
			}
 
			System.out.println("Requested line buffer size = " + SINE_PACKET_SIZE*2);
			System.out.println("Actual line buffer size = " + line.getBufferSize());
 
			ByteBuffer cBuff = ByteBuffer.allocate(SINE_PACKET_SIZE);
 
			//On each pass main loop fills the available free space in the audio buffer
	        //Main loop creates audio samples for sine wave, runs until we tell the thread to exit
	        //Each sample is spaced 1/SAMPLING_RATE apart in time
			while(bExitThread == false) {
				fFreq = m_sliderPitch.getValue();
 
				double fCycleInc = fFreq / SAMPLING_RATE;	//Fraction of cycle between samples
				cBuff.clear();								//Toss out samples from previous pass
 
				//Generate SINE_PACKET_SIZE samples based on the current fCycleInc from fFreq
				for(int i = 0; i < SINE_PACKET_SIZE / SAMPLE_SIZE; i++){
					cBuff.putShort((short)(Short.MAX_VALUE * Math.sin(2 * Math.PI * fCyclePosition)));
 
					fCyclePosition += fCycleInc;
					if(fCyclePosition > 1) fCyclePosition -= 1;
				}
				//Write sine samples to the line buffer
	            // If the audio buffer is full, this would block until there is enough room,
	            // but we are not writing unless we know there is enough space.
				line.write(cBuff.array(), 0, cBuff.position());
 
				//Wait here until there are less than SINE_PACKET_SIZE samples in the buffer
	            //(Buffer size is 2*SINE_PACKET_SIZE at least, so there will be room for 
	            // at least SINE_PACKET_SIZE samples when this is true)
				try {
					while(getLineSampleCount() > SINE_PACKET_SIZE) Thread.sleep(1);
				} catch (InterruptedException e) {
 
				}
			}
 
			line.drain();
			line.close();
		}
 
		public void exit() {
			bExitThread = true;
		}
	}
}