Found a way to handle voice recordings, decided to use this project.
Faced a problem: On Java, everything works fine, but I can't figure out how to save the result to a wav file. Here is the code:

public static void main(String args[]) throws UnsupportedAudioFileException, IOException, LineUnavailableException { // НовыС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ float speed = 1.0f; float pitch = 0.8f; float rate = 0.75f; float volume = 7.0f; boolean emulateChordPitch = false; int quality = 1; // Π§ΠΈΡ‚Π°Π΅ΠΌ Ρ„Π°ΠΉΠ» AudioInputStream stream = AudioSystem.getAudioInputStream(new File("test.wav")); AudioFormat format = stream.getFormat(); int sampleRate = (int) format.getSampleRate(); int numChannels = format.getChannels(); SourceDataLine.Info info = new DataLine.Info(SourceDataLine.class, format, ((int) stream.getFrameLength() * format.getFrameSize())); SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info); // Π€Π°ΠΉΠ» воспроизводится line.open(stream.getFormat()); line.start(); runSonic(stream, line, speed, pitch, rate, volume, emulateChordPitch, quality, sampleRate, numChannels); line.drain(); line.stop(); } 

And the runSonic method:

 private static void runSonic( AudioInputStream audioStream, SourceDataLine line, float speed, float pitch, float rate, float volume, boolean emulateChordPitch, int quality, int sampleRate, int numChannels) throws IOException { Sonic sonic = new Sonic(sampleRate, numChannels); int bufferSize = line.getBufferSize(); byte inBuffer[] = new byte[bufferSize]; byte outBuffer[] = new byte[bufferSize]; int numRead, numWritten; sonic.setSpeed(speed); sonic.setPitch(pitch); sonic.setRate(rate); sonic.setVolume(volume); sonic.setChordPitch(emulateChordPitch); sonic.setQuality(quality); do { numRead = audioStream.read(inBuffer, 0, bufferSize); if (numRead <= 0) { sonic.flushStream(); } else { sonic.writeBytesToStream(inBuffer, numRead); } do { numWritten = sonic.readBytesFromStream(outBuffer, bufferSize); if (numWritten > 0) { // Если Π·Π°ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΡƒΡŽ строчку, Ρ„Π°ΠΉΠ» Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²ΠΎΡΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚ΡŒΡΡ line.write(outBuffer, 0, numWritten); // По Π»ΠΎΠ³ΠΈΠΊΠ΅, Π² outBuffer Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒΡΡ Π±Π°ΠΉΡ‚Ρ‹ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° // Π’Ρ‹Π²ΠΎΠ΄ΠΈΠ» Π½Π° экран - ΠΌΠ½ΠΎΠ³ΠΎ Ρ€Π°Π·Π½Ρ‹Ρ… массивов Ρ€Π°Π·ΠΌΠ΅Ρ€ΠΎΠΌ 96000 // Π˜Ρ… Π½ΡƒΠΆΠ½ΠΎ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΠΈΡ‚ΡŒ ΠΈ Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ Π² Ρ„Π°ΠΉΠ», ΠΈΠ»ΠΈ ΠΊΠ°ΠΊ? } } while (numWritten > 0); } while (numRead > 0); } 

In examples of the code resulted comments.
Essence: the resulting file is played, but I need to ensure that there is no playback, but only a record to the file. I think the source code of the project makes no sense to bring, and something needs to be changed / added in the code that I gave. Thanks in advance.


UPDATE:
In the loop after line.write each time added outBuffer to the existing byte array:

 public byte[] concat(byte[] a, byte[] b) { int aLen = a.length; int bLen = b.length; byte[] c = new byte[aLen + bLen]; System.arraycopy(a, 0, c, 0, aLen); System.arraycopy(b, 0, c, aLen, bLen); return c; } 

then write it to a file:

 FileUtils.writeByteArrayToFile(file, byte_array); 

and tried to convert this file to wav, as described here .
Up to this point there are no errors, the arrays are glued correctly (checked), the file is also recorded, and so on. Even wav working. However, not without jambs: Listen to an example: link.wav . Moreover, the strangest thing is that with some settings everything is fine, while with others like in the above recording, some parts of the recording are repeated. Why and how can I fix it?


UPDATE:
I tried to write the same effective byte [] in wav, but in a different way, the result is absolutely similar. The second way here .
I use AudioFormat from the source file, that is, there can be no difference in rate / sampleSize / channels. What is the problem? During playback, everything is fine, then this result array is written to the file, and the jambs will pop out. If inBuffer is used in line.write, then it is logical that the original file will be played, and if it is written to the inBuffer file, the original recording will be recorded, but with the same jamb at the same points. If, initially, in the "new parameters" rate you specify 1.3f (no more and no less), then it turns out fine, only after the words there are pauses, as if the recording is interrupted (???). If you change this parameter, the joint can only get worse.


The entire effective record (which is played back) is divided into blocks of 96 kb each. I also combine them all into one file. I tried to save each block in a separate file and found that there are identical wav files that are obtained from completely different arrays. I calculated specially repeating blocks, looked at arrays of bytes, and at the beginning, and in the middle, and at the end, they all differ. However, the files are identical to the absolute: I opened them through a text editor, the difference is in the first few lines, that's all. So I do not understand at all what is the matter. In this case, you have to look for crutches, compare these heaps of wav files, delete duplicate ones, and then merge them into one file. But this is too crutch, and how to compare wav files is also not very clear.

    1 answer 1

    My carelessness: during playback, in the line I transferred numWritten bytes from outBuffer , and when writing to the file I transferred the array completely. Example of a working variant of writing to a file:

      // Π—Π°ΠΏΠΈΡΡŒ Π² массив byte[] result = new byte[0]; do { numRead = stream.read(inBuffer, 0, bufferSize); if (numRead <= 0) { sonic.flushStream(); } else { sonic.writeBytesToStream(inBuffer, numRead); } do { numWritten = sonic.readBytesFromStream(outBuffer, bufferSize); if (numWritten > 0) { // concat - ΠΌΠΎΠΉ ΠΊΠΎΡΡ‚Ρ‹Π»ΡŒΠ½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ для склСивания // ΠΎΠ΄Π½ΠΎΠ³ΠΎ массива с ΠΏΠ΅Ρ€Π²Ρ‹ΠΌΠΈ n элСмСнтами Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ массива result = concat(result, outBuffer, numWritten); } } while (numWritten > 0); } while (numRead > 0); // Π—Π°ΠΏΠΈΡΡŒ Π² Ρ„Π°ΠΉΠ» ByteArrayInputStream b_in = new ByteArrayInputStream(result); AudioInputStream stream_result = new AudioInputStream(b_in, format, result.length); AudioSystem.write(stream_result, AudioFileFormat.Type.WAVE, new File(result_file_path));