Перейти к содержанию
Fire Monkey от А до Я

Вопрос

Добрый день,

Может ктонибудь помочь разобраться с записью/проигрыванием звука на iOS устройствах? 
Нужно записывать звук в буффер (массив байтов). Нашли "замечатульную" библиотеку на github, которая позволяет обращаться к нативным методам устройства намрямую, и следуя инструкциям по записи звука в xCode пытаемся собрать тоже самое. Ниже привяжу ссылки... Библиотека мягко говоря не в лучшей кондиции такчто некоторые типы приходилось править вручную, и форматирование не вызывает восторга, но другого выбора нет. Если у когонибудь есть практика с другой библиотекой, или какиенибудь идеи, подскажите пожалуйста. Записывать надо обязательно в буффер, для дальнейшей обработки.

GitHub библиотека
Запись звука в xCode - github

IOS.rar

Изменено пользователем Martifan
Ссылка на комментарий

Рекомендуемые сообщения

  • 0

Советую обратить внимание на библиотеку Bass. Буквально на днях решал похожую задачу под Android (аудио чат в пределах локальной сети) с использованием данной библиотеки. Она же доступна и под iOS.

Изменено пользователем Alex7wrt
Ссылка на комментарий
  • 0
9 часов назад, Alex7wrt сказал:

Советую обратить внимание на библиотеку Bass. Буквально на днях решал похожую задачу под Android (аудио чат в пределах локальной сети) с использованием данной библиотеки. Она же доступна и под iOS.

Эх примерчик бы того как вы захватываете потом и отправляете его клиентуи как принимаете. Уже нескольок недель гуглю в этом направлении и инфы ноль. А бы ло бы интересно посмотреть как это работает. И да находил инфу что через bass.dll это делают захватывают поток с устройсва (микрофона) в событии захвата потока добавляют заголовк для куска (заголовок кодека) и передают его на клиента, но инфы о том как клиент должен это получить и воспроизвести нету да и вообще не будет ли случаем прерывании мезжу полученными кусками и как с памятью обстоят дела ? я так понимаю что для этого мазахизма выделяется какойто буфер и внесго складывается или дописываетс и наверное передача идет попакетно а не потоком (record package). (и это толкьо малая часть вопросов :()

 

Вообщем если не сложно можете поделится примером :) а то вопросов больше чем ответов

Ссылка на комментарий
  • 2
3 часа назад, Martifan сказал:

спасибо за ответ но на Android как делать этого и без использывание Bass знаю мне интересует как это сделать на iOS

Под Android я тоже делал аудио чат родными средствами, но через Bass получилось лучше и проще. В частности, там буферизация из коробки, можно эффекты накладывать, например усиление голоса при записи через микрофон. Поэтому и предложил, ведь под Bass код, что под Android, что под iOS, один и тот же.

4 часа назад, Виталий Иванов сказал:

Эх примерчик бы того как вы захватываете потом и отправляете его клиентуи как принимаете. Уже нескольок недель гуглю в этом направлении и инфы ноль. А бы ло бы интересно посмотреть как это работает. И да находил инфу что через bass.dll это делают захватывают поток с устройсва (микрофона) в событии захвата потока добавляют заголовк для куска (заголовок кодека) и передают его на клиента, но инфы о том как клиент должен это получить и воспроизвести нету да и вообще не будет ли случаем прерывании мезжу полученными кусками и как с памятью обстоят дела ? я так понимаю что для этого мазахизма выделяется какойто буфер и внесго складывается или дописываетс и наверное передача идет попакетно а не потоком (record package). (и это толкьо малая часть вопросов :()

 

Вообщем если не сложно можете поделится примером :) а то вопросов больше чем ответов

Поделиться не сложно. Ниже надергал основную схему из того приложения, о котором говорил выше.  

uses FMX.Radio.Bass;

var 
  BLoaded: boolean;
  chanPlay, ChanMic: Dword;
  avail, freq: word;
  buffer: TIDBytes;


procedure TForm1.OnCreate(Sender: TObject);
begin
    //Создаем UDP сервер 
    UDP_Rec:=TIDUDPServer.Create;
    with UDP_Rec do begin
        DefaultPort:=UDP_RecPort;
        BufferSize:=1600;
        BroadcastEnabled:=true;
        Active:=true;
    end;
    
    freq:=16000; //Частота дискретизации
    setlength(buffer,UDP_Rec.BufferSize);

    BLoaded:=BASS_Init(-1, 44100, 0, nil, nil); //Подключаем библиотеку
    BASS_RecordInit(-1); //Инициализируем запись
end;

//Захват звука с микрофона
procedure TForm1.Recording(Sender: TObject; const Point: TPointF);
begin
    isrecording:=not isrecording;
    if isrecording then begin
        UDP_Rec.OnUDPRead:=nil;
        chanMic:=BASS_RecordStart(freq, 1, 0, nil, nil);
        VoiceThread:=TVoiceThread.Create; //Создание потока для отправки по UDP
    end
end;

//Передача буффера в потоке
procedure TVoiceThread.Execute;
begin
    while isrecording do begin
        try
            avail:=BASS_ChannelGetData(chanMic, nil, BASS_DATA_AVAILABLE);
            if avail>=UDP_Rec.BufferSize then begin //Если в буффере собралось не меньше 1600 байт, отправляем
                try
                    BASS_ChannelGetData(chanMic, buffer, UDP_Rec.BufferSize);
                    UDP_Rec.Broadcast(Buffer,UDP_RecPort);
                except
                end;
            end;
        finally
            sleep(20);
        end;
    end;
    BASS_ChannelStop(chanmic);
    BASS_StreamFree(chanmic);
end;


//Создание канала для воспроизведения звука из буффера:
procedure TForm1.receiving(Sender: TObject);
begin
    chanPlay:= BASS_StreamCreate(freq, 1, 0, STREAMPROC_PUSH, nil);
    UDP_Rec.OnUDPRead:=UDP_RecRead;
    BASS_ChannelPlay(chanPlay, false);
end;

//Получаем буффер из UDP
procedure TForm1.UDP_RecRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle);
begin
    try
        BASS_StreamPutData(chanPlay, AData,length(AData))
    except
    end;
end;

Bass.zip

Изменено пользователем Alex7wrt
Ссылка на комментарий
  • 0
28 минут назад, Martifan сказал:

Opus это кодек который сжимает буфер и гораздо быстрее работает чат пре плохом интернете

Это я понял, пример бы тоже был как ни ксате замечательным дополнением темы :)

Ссылка на комментарий
  • 0
41 минуту назад, Виталий Иванов сказал:

Это я понял, пример бы тоже был как ни ксате замечательным дополнением темы :)

сам у Bass есть этот модуль разберусь и результат вылажу

Ссылка на комментарий
  • 0
2 часа назад, Martifan сказал:

все хорошо спасибо большое
это все еще через Opus прогнать и будет просто супер

Методом проб и ошибок обнаружил, что для речи запись с частотой дискретизации 16000 выдает практически такое же качество, как и 44100, но ощутимо лучше, чем 8000. При этом используется одноканальная запись (моно), что с учетом 16 бит на семпл дает 32 кБ/с (256 кбит/с), что не сильно нагружает WiFi сеть. Потерь нет (и это в UDP протоколе).

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

Ссылка на комментарий
  • 0
4 минуты назад, Alex7wrt сказал:

Методом проб и ошибок обнаружил, что для речи запись с частотой дискретизации 16000 выдает практически такое же качество, как и 44100, но ощутимо лучше, чем 8000. При этом используется одноканальная запись (моно), что с учетом 16 бит на семпл дает 32 кБ/с (256 кбит/с), что не сильно нагружает WiFi сеть. Потерь нет (и это в UDP протоколе).

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

да но при плохом интернете у вас будет дерганье речи или если это UDP вообще не дойдёт поток

Ссылка на комментарий
  • 0

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

Изменено пользователем Alex7wrt
Ссылка на комментарий
  • 0

Можно еще поиграться с размером буфера в Bass, который измеряется в миллисекундах и по умолчанию равен 500. Чем он больше, тем меньше вероятность потерь, но больше задержка звука при стримминге.

Ссылка на комментарий
  • 1

Кому юудет интересно, собрал мини проект по примеру выше. Звук передает как ни странно, и да же приемлемого качества с минимальной задержкой :) спасибо всем кто участувет в этой теме :)

Сразу извиняюсь за говно код внутри примера, делалось не для эстетики, а показать другим что пример рабочий. :)

Chat Test_09.06.2018_19-04.rar

Изменено пользователем Виталий Иванов
Ссылка на комментарий
  • 0

Теперь есть отправная точка :)  как это должно, теперь буду дальше эксперементировать. Нужно сделать теперь ещё сервер для того что бы это работало через NAT и проверить работу на Android

Ссылка на комментарий
  • 0
В 08.06.2018 в 14:44, Martifan сказал:

сам у Bass есть этот модуль разберусь и результат вылажу

Вечер добрый! И как успехи с прикручиванием кодека?

Изменено пользователем IVGSoft
Ссылка на комментарий

Присоединяйтесь к обсуждению

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

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...