Порт SoX для Android или попытка создать идеальный плеер

    Здравствуй, Хабраюзер!

    Несколько месяцев назад у меня появилась идея создания плеера под Android с огромным количеством эффектов. Единственным на то время (не знаю как сейчас:) плеером, с хоть какой-то обработкой звука, был PowerAMP, но количество аудио-эффектов в нем было мягко говоря скудным. Я попробовал реализовать эту идею. Из этого мало что вышло, но то, что получилось я расскажу в этом топике. Итак, кого заинтересовало, прошу под кат.

    В поисках библиотеки...


    Для начала я решил найти ту самую OpenSource библиотеку, которая может гибко обрабатывать звук, применяя различные эффекты. В конце концов я случайно познакомился с SoX. С первого взгляда это была идеальная библиотека для реализации такого проекта, но, оказалось, не все так просто…

    Первые проблемы


    По ходу знакомства с SoX я обнаружил такие проблемы:
    1. Библиотека отлично работает на всех основных ОС, НО не оптимизирована под ARM.
    2. Описание API библиотеки, как и само API, было достаточно скудным, почти все функции было проще реализовывать через командную строку.
    3. SoX, вместо того, чтобы использовать один FFmpeg для декодирования, использует целый ряд библиотек (можете посмотреть на официальном сайте). Следовательно, все эти библиотеки так же придется собирать под Android NDK.
    4. SoX отлично воспроизводил и декодировал практически любые форматы, но, при применении эффектов, аудио можно было либо декодировать в файл или byte массив, либо воспроизвести через Alsa/CoreAudio. Третий вариант не подходил однозначно, так как в Андроид Alsa теоретически есть, но работает не всегда и, вообще, это не рекомендованый метод воспроизведения звука. Следовательно, единственный вариант — декодировать все в byte массив и отдавать его в Java (AudioTrack). Но даже это реализовать оказалось достаточно сложно, так как… объясню на примере:)
    Вот часть кода официального примера применения обработки звука с использованием эффектов:

    
      assert(sox_init() == SOX_SUCCESS);
      assert(in = sox_open_read(argv[1], NULL, NULL, NULL));
      /* Change "alsa" in this line to use an alternative audio device driver: */
      assert(out= sox_open_write("default", &in->signal, NULL, "alsa", NULL, NULL));
    
      chain = sox_create_effects_chain(&in->encoding, &out->encoding);
    
      e = sox_create_effect(sox_find_effect("input"));
      args[0] = (char *)in, assert(sox_effect_options(e, 1, args) == SOX_SUCCESS);
      assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS);
    
      e = sox_create_effect(sox_find_effect("trim"));
      args[0] = "10", assert(sox_effect_options(e, 1, args) == SOX_SUCCESS);
      assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS);
    
      if (in->signal.rate != out->signal.rate) {
        e = sox_create_effect(sox_find_effect("rate"));
        assert(sox_effect_options(e, 0, NULL) == SOX_SUCCESS);
        assert(sox_add_effect(chain, e, &in->signal, &out->signal) == SOX_SUCCESS);
      }
    
      if (in->signal.channels != out->signal.channels) {
        e = sox_create_effect(sox_find_effect("channels"));
        assert(sox_effect_options(e, 0, NULL) == SOX_SUCCESS);
        assert(sox_add_effect(chain, e, &in->signal, &out->signal) == SOX_SUCCESS);
      }
    
      e = sox_create_effect(sox_find_effect("output"));
      args[0] = (char *)out, assert(sox_effect_options(e, 1, args) == SOX_SUCCESS);
      assert(sox_add_effect(chain, e, &in->signal, &out->signal) == SOX_SUCCESS);
    
      sox_flow_effects(chain, NULL, NULL);
    

    В данном случае аудио декодируется, и применяется несколько эффектов, затем все выводится через ALSA. Как видите для того, чтобы создать effect_chain надо сначала иметь 2 потока: для чтения и для вывода информации. Вот официальный пример декодирования аудио файла по частям в byte array:
    
      assert(sox_init() == SOX_SUCCESS);
    
      /* Open the input file (with default parameters) */
      assert(in = sox_open_read(argv[1], NULL, NULL, NULL));
    #if defined FIXED_BUFFER
      assert(out = sox_open_mem_write(buffer, buffer_size, &in->signal, NULL, "sox", NULL));
    #else
      assert(out = sox_open_memstream_write(&buffer, &buffer_size, &in->signal, NULL, "sox", NULL));
    #endif
      while ((number_read = sox_read(in, samples, MAX_SAMPLES)))
        assert(sox_write(out, samples, number_read) == number_read);
    

    Как видите, в данном случае аудио декодируется частями, и программа получает буфер. Этот пример полностью рабочий, НО в нем практически невозможно применить эффекты (что и является целью программы), потому что для этого пришлось бы для каждой части аудио (размеров в 16484 байта) создавать поток чтения и записи в другой буфер и затем эти потоки обрабатывать. У меня это не вышло, да и ни в одном примере такая возможность не описана.
    Тогда логично было бы декодировать все аудио с применением эффектов в один буффер, НО этот вариант использует много оперативной памяти (когда я тестировал доходило до 100 мб при декодировании небольшого аудио файла в 10-11 мегабайт).

    Но все-таки решено попробовать...


    Не смотря на эти проблемы, я решил начать портировать SoX и все сопутствующие библиотеки. Неделя ушла на знакомство с Android NDK. В принципе портирование было не сложным, однотипным процессом, который я описывал в прошлой статье. Некоторые библиотеки уже были собраны (например FFmpeg). В конце концов я получил скомпилированный sox.so, который действительно работал и работает сейчас:) Пришло время решить проблему 3. Все оказалось не слишком сложно — создал отдельный поток, который по мере заполнения буфера отправляет его в Java программу, а та его воспроизводит. Проблема с памятью почти решена (все-таки ее используется много, но приложение это не роняет). Я получил приложение которое воспроизводит почти все форматы аудио и добавляет к нему эффекты (сейчас flanger, можно добавить любой другой). С одной стороны уже можно продолжать разработку, НО я получил сразу две новые проблемы:

    1. Программа слишком сильно использует процессор (доходит до 80% при декодировании). Оптимизировать С код под ARM я не умею, поэтому решить это самостоятельно не вижу возможным.
    2. Программа работает нестабильно. Приблизительно 1-2 из 10 запусков она ничего не воспроизводит (тестировал на Galaxy Tab). Эту проблему я так же не мог решить…

    Итого, чтобы работа не пропала, я решил опубликование весь код на GitHub и написать статью тут. Ссылка на код. Если кто-то видит возможности решить эти проблемы — пишите мне в email или в личку. Надеюсь моя задумка кого либо заинтересует:)

    Средняя зарплата в IT

    110 000 ₽/мес.
    Средняя зарплата по всем IT-специализациям на основании 8 657 анкет, за 2-ое пол. 2020 года Узнать свою зарплату
    Реклама
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее

    Комментарии 44

      –1
      Идеальный != много эффектов.
      На Android на моей памяти (на момент августа 2011 года) не было вообще ни одного нормального плеера который мог бы выполнять хотя бы скудный набор базовых функций.
      Сделайте черт возьми хоть один нормальный плеер не требущий излишнего внимания.
      Будет счастье.
        +5
        PowerAMP? WinAMP? MIUI Plyer? Что именно они не умеют?
          0
          MIUI Plyer не юзал, остальные не умели прогирывать корректно например аудиокниги или большие файлы, не дай бог на паузу нажать или звонок принять, пипец слушай всё с начала.
          Не говоря уже про интерфейс, про возможность управления с гарнитуры, короче всё то что умеет айфон из коробки, и некоторые модели HTC Android с каким то своим плеером.
            +1
            Слушаю аудиокниги в winamp (на Samsung Gio), ставлю на паузу (или вытаскиваю наушники), при следующем запуске начинает с того же места. В настройки вроде никогда не лазил, по умолчанию так и работает со дня установки.
              –4
              Сомневаюсь что дело в железе, но я перепробовал все имеющиеся бесплатные плеера из маркета, лажали так или иначе все кто в одном кто в другом. Банально переключить трек с гарнтируры оказалось верхом совершенства.
                0
                Power Amp переключает плеер с гарнитуры по-умолчанию.
                  0
                  Не пробовал большие файлы, но управление с гпрнитуры и адекватная пауза в наличии + небольшие твоей звука + настраеваемый виджет и на последок умеет играть по папками MortPlayerMusic, попробуйту. Для себя лучше не вижу плееоа.
                    0
                    Извиняюсь за ошибки, в маршрутке с Таба пишу)
              • НЛО прилетело и опубликовало эту надпись здесь
                  0
                  А теперь вопрос — что у вас за железяка? Миуи плэйлр вы не попробуете, это часть MIUI ROM, и без библиотк этой прошивки он не заведётся. Все перечисленные вами функции есть во всех трёх озвученных мною плеерах, и, как видите, у меня (и у других людей) они работают. Пемсим, полагаю?

                  Итак, озвучу свой вопрос ещё раз:
                  Модель телефона
                  Версия П.О.
                  Использованная гарнитура

                  Информацию фстудию.
                    –1
                    Xperia X10i
                      0
                      Неправда ваша. prooflink
                        0
                        Древняя, аки маммонтовы говна версия. Сейчас и выглядит иначе, и работает куда лучше. По качеству звучания сравнимо с PowerAMPом, только чуть мягче и басов побольше (на плоском эквалайзере). Скажем так, звучание мне даже чуть больше нравится в нём, а вот PowerAMP просто давно уже куплен и интерфейсом привычен, так что на нём и сижу пока что.
                          0
                          и тем не менее, не стоит так категорически заявлять.
                            0
                            Cкажем так, я не имел ввиду того, что никакими путями не получить MIUI-проигрыватель без всей прошивки, скорее, хотел сказать, что без неё он не имеет смысла. Это как порт одной отдельной проги с iOS, который вроде как и осуществлён, но смысла без всего остального — мало.
                      0
                      Рекомендую для аудиокниг попробовать MortPlayer AudioBook. Он умеет сохранять позиций для каждого трека, закладки и тд. и тп. Вообще все что нужно для комфортного прослушивания аудиокниг.
                        0
                        Большие файлы прекрасно проигрыввает PlayerPro Music Player, запоминает место остановки и управляется с гарнитуры, есть эквалайзер, проигрывает папки, плагины и всякое такое. Но, я бы для аудиокниг рекомендовал вам специальный плеер для этих самых книг (сам пользуюсь Ambling BookPlayer Pro). Всё есть, главное, поискать.
                          –1
                          Айтюнс на айфоне делал это всё сразу и из коробки без лишних действий. А то что можно найти кучу разных инструментов под задачи я уверен, вот только хочется один простой и рабочий и с терпимым дизайном, а такого нет, или он встроен в HTC модели некоторые и то не идеал.
                            0
                            Я не понимаю, Вы что капризничаете? Вы жаловались на отсутствие нормального (в субъективном плане, конечно) плеера, Вам посоветовали уже кучу программ (не думаю, что Вы успели все их проверить на «нормальность») и вот Вы уже говорите про айтюнс, из коробки… к чему это?
                              –1
                              Я говорю о том что можно пойти и купить риса, рыбы, икры, и так далее, и сделать суши.
                              А можно пойти в ресторан и съесть их.
                              Вот когда я говорю про айтюнс из коробки который полностью покрывал все потребности, я имею ввиду, что нет ни какого гемороя с этим, бац и работает всё как ожидаешь.
                              Когда как на андроиде приходится то и дело искать то рис то рыбу, и в итоге жрать всё это по отдельности.
                              Вот и всё, это не каприз это правда жизни.
                              Нормального плеера на андроиде нет просто.
                              И да, про проверить, слава богу что я не использую больше этих андроид убожеств, пусть теперь другие мучаются, и они мучаются.
                              Вообще хорошо когда есть вера и желание преодолевать препятствия на пути, но чаще всего это от скуки.
                              Собственно если скучно то конечно можно сидеть и искать тот самый плеер, но на моей памяти такие спорщики как вы затыкались уже на 7 предложении нового плеера который ну на этот раз точно решает базовые задачи :-)) потому как они все решали их по отдельности.
                      +3
                      Я лично не фанат всех этих эффектов в аудио-плеерах на телефонах — всё равно отдельного dsp-чипа для аудио нет.
                      И в связи с этим мне лично нравится вот этот минималистичный плеер, советую посмотреть — AndLess
                      +3
                      А зачем эффекты?
                        0
                        возможно будет интересно: github.com/glastonbridge/SuperCollider-Android
                        • НЛО прилетело и опубликовало эту надпись здесь
                            0
                            фрутилупса нету, есть Caustic
                              0
                              Ну почему же. Если вам не надо, может быть многим другим людям надо. Почему многие люди выбирают плеерв роде PowerAMP с эквалайзером и прочим, а не минималистический AndLess? Потому что многим как раз хочется обрабатывать музыку про прослушивании.
                                0
                                И согласитесь, все таки SoX создается с 91 года и его используют достаточное количество людей, именно благодаря огромному количеству аудио эффектов. Кому то не надо, но кто-то только этого и ждет…
                              0
                              Если так хочется эффектов — юзаем паверАМП, или стоковый плеер, и рядом просто ставим dspmanager и еще к-нить сторонний эквалайзер. А если еще и ограничение на громкость звука разблокировать — сказка будет.
                                +2
                                Если вы юзали DSP менеджер, то наверное видели, что там всего пару эффектов. Я же хотел сделать намного большее количество:)
                                +1
                                А какой эффект еще нужен хорощему аудиоплееру, кроме эффекта проигрывать музыку при нажатии на кнопку Play в виде, задуманном и записанном автором музыки? ;-}
                                  +1
                                  Есть еще к примеру MortPlayer, его использую и никаких проблем не ощущаю.
                                    –2
                                    Идеальный плеер, который похож на маленький iTunes, оптимизирован на расход энергии скромен до памяти
                                      0
                                      Идеальный плеер — субъективное понятие. Для минималиста оно именно таким и будет.
                                        –4
                                        Минимальность это кнопка Play, я думаю она вас не устроит, помолчите лучше
                                          0
                                          Не затыкайте мне рот. Вас так обидело слово — минималист? И, кажется, вы передергиваете, никто не против кнопки play, но кроме ее есть много других функций. Если вам они не нужны, молчите сами.
                                      +1
                                      По поводу оптимизации: попробуйте дописать в Android.mk
                                      LOCAL_CFLAGS := -DFPM_ARM -ffast-math -O3
                                        0
                                        Спасибо, попробую.
                                        +1
                                        По поводу нестабильности мне попалась неутешительная статья Android Audio: Problems, Hidden Limitations and OpenSL ES" с выводом, что AudioTrack бажный и фактически не работает как должен.
                                          –2
                                          Умеет открывать файлы по вайфаю?
                                            0
                                            Можно поподробнее: какие все таки эффекты в конечном счете нужны?
                                            Кстати, вышел новый Winamp, в PRO версии доступен 10ти полосный эквалайзер, воспроизведение из папки, поддержка FLAC и т.д., но 5$ за эквалайзер -это они конечно перегнули. В комментах на маркете, кстати, народ пишет что что-то там не работает, я Pro версию проверил — у меня на МотоДефи все без проблем играет, эквалайзер пашет, ничего не заикается, радио ловит.
                                              0
                                              Прочитайте на сайте сокса. Там есть перечень эффектов которые дает их библиотека. Приблизительно штук 15 набереться, учитывая flanger, stereo enhancer, эквалайзер и тому подобное.
                                                0
                                                Спасибо, я читал en.wikipedia.org/wiki/SoX
                                                Я считаю что альтернативный и функциональный плеер нужен, но вопрос мой заключался в следующем: какие эффекты в конечном счете будут востребованы?
                                                Как я выше уже сказал: меня и Винамп устраивает, даже множество доп фич PowerAMP мне не нужны.
                                                Из тех, что заявлены у SOX опишу свое мнение:
                                                -Reading and writing AU, WAV, AIFF, MP3 (via an external LAME MP3 encoder), Ogg Vorbis, FLAC and other audio file formats — всеядность форматов, полезно!
                                                -Recording and playing audio (on many systems); playing via URL (internet file or stream) — многим пригодится
                                                -Editing via concatenate, trim, pad, repeat, reverse, volume, fade, splice, normalise — функции аудиоредактора тоже пригодятся
                                                -Processing via chorus, flanger, echo, phaser, compressor, delay, filter (high-pass, low-pass, shelving, etc.) — мне лично функции эха и дисторшна и т.д. не очень нужны — это же плеер
                                                -Adjustment of speed (pitch and tempo), pitch (without tempo), tempo (without pitch), and sample-rate — эта функция мне тоже не нужна, я не диджей
                                                -Noise removal using frequency profiling — шумоподавление пригодится, вдруг найду какую нибудь ужасную по качеству мп3шку
                                                -Statistical analysis; spectrogram analysis — интересная вещь!
                                                -Multi-file & multi-track mixing
                                                -Multi-file merging (e.g. 2 mono to 1 stereo) — эти две функции мне навряд ли пригодятся
                                                В идеале должен мощный комбайн получиться.
                                                Желаю Вам удачи!
                                                  0
                                                  Пользуясь случаем, хочу напомнить о порте известного RockBox
                                                  www.rockbox.org/wiki/AndroidPort
                                                  ru.wikipedia.org/wiki/Rockbox
                                                    0
                                                    Абсолютно согласен. Я и хочу создать максимально мощный комбаин. Насчет этого:
                                                    -Processing via chorus, flanger, echo, phaser, compressor, delay, filter (high-pass, low-pass, shelving, etc.)
                                                    да, это на любителя, но все таки кому нибудь может понадобиться. Меня лично привлекает больше stereo enhancer, его нет в єффектах сокса готового, но можно попробовать создать самому (ведь можно руководить каналами теоретически). все так объемное звучание — достаточно эффектная штука.

                                                    О RockBox слышал. Да кодеки у него все есть и достаточно отлично работают, насколько я понимаю, НО эффектов нет, поэтому «мега комбаин» создать не выйдет:( Просто я думаю, что если ориентироваться на рокбокс то выйдет не лучше чем PowerAMP…

                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                            Самое читаемое