Чтобы изменить высоту звука аудиофайла в определенных местах в файлах, используя коды в java ниже

Я хочу изменять высоту звука аудиоклипа динамически на основе ввода пользователя в разные моменты времени, скажем, если пользователь вводит изменение высоты звука через 10 секунд, как я могу добиться того же?

Я нашел эту ссылку, в котором описывается, как изменить высоту звука, но я хочу повторить этот процесс в разные моменты времени аудиоклипа и только в течение некоторого короткого промежутка времени. Кто-нибудь может помочь мне в этом?

Некоторые правки

Изменить 1

Я нашел этот код, как я уже упоминал ранее

//source file
final File file1 = new File(“Sample.mp3”);
//destination file
final File file2 = new File(“Sample_cat.wav”);
//audio stream of file1
final AudioInputStream in1 = getAudioInputStream(file1);
//get audio format for targetted sound
final AudioFormat inFormat = getOutFormat(in1.getFormat());
//change the frequency of Audio format
private AudioFormat getOutFormat(AudioFormat inFormat) {
        int ch = inFormat.getChannels();
        float rate = inFormat.getSampleRate();    
        return new AudioFormat(PCM_SIGNED, 72000, 16, ch, ch * 2, rate,
                inFormat.isBigEndian());
    }
//get the target file audio stream using file format
final AudioInputStream in2 = getAudioInputStream(inFormat, in1);
//write the audio file in targeted pitch file
AudioSystem.write(in2, AudioFileFormat.Type.WAVE, file2);

РЕДАКТИРОВАТЬ 2. Я нашел другой код, который устанавливает позицию аудиофайла, с которой вы хотите начать и остановить звук.

        File audioFile = new File(audioFilePath);


        AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);

        AudioFormat format = audioStream.getFormat();

        DataLine.Info info = new DataLine.Info(Clip.class, format);

        Clip audioClip = (Clip) AudioSystem.getLine(info); 
        audioClip.open(audioStream);
        audioClip.setLoopPoints(10_000, 500_000);
        audioClip.loop(1);

Теперь, как я могу изменить высоту тона на время, установленное в Редактировать 2, то есть с 10 мс до 50 мс, с помощью кода в Редактировать 1

Кто-нибудь может мне посоветовать, могу ли я сделать то же самое другими способами, кроме Java? тогда предложения приветствуются ... Пожалуйста, помогите. Я новичок в этом.

** Редактировать 3 **

Точную проблему можно указать по этой ссылке: ссылка

Это значения (в миллисекундах), о которых я говорю:

public static void convertMsgToAudio(String msg){

        int len = msg.length();
        duration = new double[len];
        msg = msg.toUpperCase();
        System.out.println("Msg 2 : " + msg);

        int i;
        //char ch;
        for(i=0;i<msg.length();i++){

            if(msg.charAt(i) == 'A'){
                duration[i] = 50000;
            }
            else if (msg.charAt(i) == 'B'){
                duration[i] = 100000;
            }
            else if (msg.charAt(i) == 'C'){
                duration[i] = 150000;
            }
            else if (msg.charAt(i) == 'D'){
                duration[i] = 200000;               
            }
            else if (msg.charAt(i) == 'E'){
                duration[i] = 250000;
            }
            else if (msg.charAt(i) == 'F'){
                duration[i] = 300000;
            }
            else if (msg.charAt(i) == 'G'){
                duration[i] = 350000;
            }
            else if (msg.charAt(i) == 'H'){
                duration[i] = 400000;
            }
            else if (msg.charAt(i) == 'I'){
                duration[i] = 450000;
            }
            else if (msg.charAt(i) == 'J'){
                duration[i] = 500000;
            }
            else if (msg.charAt(i) == 'K'){
                duration[i] = 550000;
            }
            else if (msg.charAt(i) == 'L'){
                duration[i] = 600000;
            }
            else if (msg.charAt(i) == 'M'){
                duration[i] = 650000;
            }
            else if (msg.charAt(i) == 'N'){
                duration[i] = 700000;
            }
            else if (msg.charAt(i) == 'O'){
                duration[i] = 750000;
            }
            else if (msg.charAt(i) == 'P'){
                duration[i] = 800000;
            }
            else if (msg.charAt(i) == 'Q'){
                duration[i] = 850000;
            }
            else if (msg.charAt(i) == 'R'){
                duration[i] = 900000;
            }
            else if (msg.charAt(i) == 'S'){
                duration[i] = 950000;
            }
            else if (msg.charAt(i) == 'T'){
                duration[i] = 1000000;
            }
            else if (msg.charAt(i) == 'U'){
                duration[i] = 1100000;
            }
            else if (msg.charAt(i) == 'V'){
                duration[i] = 1200000;
            }
            else if (msg.charAt(i) == 'W'){
                duration[i] = 1300000;
            }
            else if (msg.charAt(i) == 'X'){
                duration[i] = 1400000;
            }
            else if (msg.charAt(i) == 'Y'){
                duration[i] = 1500000;
            }
            else if (msg.charAt(i) == 'Z'){
                duration[i] = 1600000;
            }

        }

    }

person POOJA GUPTA    schedule 18.03.2015    source источник
comment
Никто не может мне в этом помочь?   -  person POOJA GUPTA    schedule 18.03.2015
comment
Кто-нибудь может мне посоветовать, могу ли я сделать то же самое другими способами, кроме Java? тогда предложения приветствуются ...   -  person POOJA GUPTA    schedule 18.03.2015


Ответы (1)


Насколько мне известно, Java не предоставляет данные в клипе для редактирования.

Я никогда не пробовал изменять высоту звука, изменяя частоту дискретизации. Может быть, это хороший способ пойти. Есть раздел руководств по Java, в котором рассматриваются изменения в форматировании файлов wav: Использование файлов и конвертеры формата. Похоже, это будет хорошая справочная информация и может даже охватить решение, которое вы пытаетесь использовать.

Вот что я делаю, называю это VarispeedWavPlayer.

(1) иметь переменную float изменчивого экземпляра, которая является коэффициентом скорости (1 - та же скорость, 1,1 - 110%, 0,5 - половинная скорость и т. Д.

(2) иметь поплавок, который будет бегущей лентой

(3) начните с обычного кода для чтения из AudioInputStream и вывода в SourceDataLine (хороший пример в «Чтении звуковых файлов» в приведенной выше ссылке на Руководство по Java.

(4) в области, где есть комментарий

// Here, do something useful with the audio data that's 
// now in the audioBytes array...

(а) преобразовать входящие байты в данные PCM.

Пример того, как это сделать, с 16-битным кодированием, стерео, с прямым порядком байтов ("качество компакт-диска"). Это использует размер буфера чтения 1024 байта, который преобразуется в 256 кадров (помните, есть две дорожки, левая и правая) коротких данных в диапазоне от -32767 до 32767 (или, может быть, 32768, я не могу вспомнить эту деталь в момент).

while((bytesRead = audioInputStream.read(rawByteBuffer, 0, 1024)) != -1)
{
    for (int i = 0, n = bytesRead / 2); i < n; i ++)
    {
        pcmBuffer[i] =  ( rawByteBuffer[i * 2] & 0xff )
                        | ( rawByteBuffer[(i * 2) + 1)] << 8 ) ;
    }
}   

Вышеупомянутое было отредактировано для большей ясности и может потребовать некоторой оптимизации производительности.

(b) получить текущий «коэффициент скорости» и написать цикл, который перебирает значения кадра PCM (имея в виду, что в стерео, «следующий» кадр для этой дорожки равен +2):

tapehead += speedfactor;

(c) это обычно приземляется по дробной стоимости. Используйте линейную интерполяцию, чтобы вычислить значение в этой промежуточной точке. Например, если вы приземлитесь на tapehead = 10,25, а кадр 10 равен 0,5, а кадр 11 равен 0,6, вы вернете 0,525.

(d) преобразовать интерполированные значения обратно в байты (в обратном порядке к шагу 4a)

(e) накапливать байты и отправлять их через SourceDataLine.

Я упустил некоторые детали с точки зрения управления тем фактом, что входные и выходные байтовые буферы не будут соответствовать однозначно. Но если вы усвоите основную концепцию, то я думаю, вы сможете решить эту проблему.

Обратите внимание: это обновит скорость только в момент обращения к переменной "speedFactor", один раз для каждого входного буфера. Таким образом, вы не хотите, чтобы входной буфер был слишком большим.

person Phil Freihofner    schedule 19.03.2015
comment
спасибо за ответ :) Но я плохо разбираюсь в звуке .. в частности, я не понимал, как конвертировать входящие данные в PCM .. - person POOJA GUPTA; 19.03.2015
comment
и послесловия ... так что, если вы можете предоставить мне код для этого, а не псевдокод, это будет большим подспорьем ... поскольку у меня заканчивается время, и я не очень хорошо разбираюсь в java ... но у меня нет другого выбора .. - person POOJA GUPTA; 19.03.2015
comment
Каждый из шагов был рассмотрен в StackOverflow. Я думаю, вы добьетесь успеха, если поищете их. У меня тоже мало времени. Возможно, вы откусили немного больше, чем вы готовы, поскольку для этого требуется больше, чем просто уровень навыков программирования на Java новичка. - person Phil Freihofner; 19.03.2015
comment
спасибо за ваш совет, я сделаю немного по этому поводу ... вы можете сказать мне еще кое-что ... я указал точную проблему на stackoverflow.com/questions/29138169/ .. не могли бы вы сказать мне, поможет ли мне в достижении этого способ, которым вы говорите? ..? заранее спасибо :) - person POOJA GUPTA; 19.03.2015
comment
Чтобы взять два байта (предполагает 16-битную кодировку с прямым порядком байтов) и преобразовать в PCM в диапазоне от -32767 до 32767, попробуйте эту строку кода: int audioVal = (buffer [i + 1] ‹‹ 8) | (буфер [i] & 0xff); // Я попытался выполнить поиск и не могу найти похожие сообщения. Я знаю, что они были здесь! - person Phil Freihofner; 19.03.2015
comment
Я действительно думаю, что описанный мной метод может это сделать. В прошлом я писал следующее: код для воспроизведения файла wav через SourceDataLine с заданной скоростью (быстрее, медленнее). Я еще не делал ту часть, где меняют скорость на полпути, раньше. Но ваше описание выставления счета за убийство немного проще реализовать, чем то, что я описал для эффектов изменения высоты тона в реальном времени. - person Phil Freihofner; 19.03.2015
comment
Я отредактировал свой вопрос ... взгляните на него один раз ... и еще одна вещь, о которой вы мне рассказываете, это не похоже на ответ, опубликованный по ссылке, которую я дал ... хотя он на python? - person POOJA GUPTA; 19.03.2015
comment
это та ссылка, о которой вы говорили? stackoverflow .com / questions / 12120399 / - person POOJA GUPTA; 19.03.2015
comment
Можете ли вы предоставить мне код ... извините за такой вопрос, но я пробовал много разных вещей, и они не работают ... не это, а еще кое-что ... будет здорово, если вы поможете мне с кодом ... - person POOJA GUPTA; 19.03.2015
comment
Я добавил код в 4a, чтобы помочь с преобразованием 16-битных закодированных байтов в PCM. Этот ответ отличается от ответа, приведенного в вашей версии Python. У меня нет опыта использования такого подхода (см. 2-й абзац). Если вы действительно отчаянно нуждаетесь в том, чтобы кто-то написал для вас код, вы можете подумать о добавлении вознаграждения или найме репетитора / кодера. Чем больше вы просите людей предоставить вам код, тем выше риск получить ярлык вампира-справки meta.stackexchange.com/questions/19665/the-help-vampire-problem - person Phil Freihofner; 19.03.2015
comment
@Ohil Freihofner: спасибо за совет :) но проблема не в том, что я не могу кодировать, проблема в том, что я не могу понять, что вы пытаетесь сделать в этом коде ... не понимая логики, вы не можете ничего кодировать .. если Я не ошибаюсь? Я пытался понять линейную интерполяцию ... но по звуку это был совершенно другой код, чем тот, который парень написал на python, который также делал линейную интерполяцию ... спасибо за вашу помощь до сих пор ... поверьте мне, я не из тех людей кто будет продолжать просить код, но на этом этапе помогла бы небольшая вещь .. :) - person POOJA GUPTA; 20.03.2015
comment
эй, я начал немного разбираться в коде ... просто для пояснения ... это tapehead переменная, то есть переход к желаемому сэмплу, высоту которого мы хотим изменить, а speedfactor - это переменная, которая представляет количество кадров, которые помогают в переход к желаемому кадру? - person POOJA GUPTA; 20.03.2015
comment
Да, я думаю, вы это понимаете. Много чего переварить, если это новое! Аналогия: головка ленты читает пропущенную ленту. При нормальном чтении (если лента представляла собой цифровой поток цифр вместо аналоговой волны) лента продвигается на 1 пробел (используется для 1 кадра), и tapeHead считывает этот кадр. При ускоренном чтении лента продвигается, скажем, на 1,7 пробела (вместо 1), а tapeHead интерполирует это значение, которое будет между кадром 1 и кадром 2. Иногда термин курсор используется для переменной, которая постепенно перемещается по массиву. tapeHead - это курсор. Для приличного звука достаточно линейной интерполяции. - person Phil Freihofner; 20.03.2015
comment
Извините, но вы можете сказать мне еще одну вещь ... массив длительности, который я упомянул в своем вопросе, имеет значения в миллисекундах ... так что сначала я должен преобразовать их в кадры? эта продолжительность будет эквивалентна коэффициенту скорости, верно? Если мой начальный ответвитель находится в кадре 1, а коэффициент скорости (= некоторое значение длительности) представляет собой некоторое плавающее значение, то добавление его к кадру 1 дает мне, скажем, кадр 10, тогда в кадре линейной интерполяции 1 и кадре 10 изменяется высота тона для всех от 1 до 10. ? - person POOJA GUPTA; 20.03.2015
comment
Я просто хочу, чтобы после того, как вы преобразовали данные в значения выборки PCM ... итерация по массиву длительности, чтобы ... все образцы, которые лежат в каждой из длительностей, были изменены с новым значением высоты тона ... Я думаю, теперь вы лучше поймете, что Я хочу сказать ... Просьба уточнить это :) - person POOJA GUPTA; 20.03.2015
comment
Входящий звук - это стерео 44100 кадров в секунду, вероятно (зависит от ваших исходных файлов), и никогда не меняется. Если вы хотите, чтобы миллисекунды от 1000 до 3000 шли на 3/4 скорости источника, то, когда вы дойдете до кадра 44100, начните увеличивать tapeHead на 0,75, пока не пересечете кадр 132300 (3 * 44100). Если вы подсчитываете входящие байты вместо кадров, умножьте полученное выше на 4 (при условии 4 байта на кадр). Когда ваш tapeHead пересекает пороговое значение для следующей скорости, вычислите новое значение speedIncrement и продолжайте. Если вы хотите идти на 1/4 БЫСТРЕЕ, чем источник, speedIncrement будет 1,25. - person Phil Freihofner; 20.03.2015