Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 02.01.2017, 08:46   #1
АНАТОЛИЙ249
Пользователь
 
Регистрация: 05.02.2007
Сообщений: 91
По умолчанию Воспроизводит звук из буфера или потока с помощью BASS.dll

Пишу голосовой чат , нужно воспроизвести звук mp3 из буфера или потока, делаю так, получаю данные от клиента отдаю bass.dll , звук идет но с перерывами, потому что данные отдаю в memorystream ,а memorystream воспроизвожу, так как размер memorystream имеет размер , то bass.dll проигрывает его ,до конца и закрывается ,затем приходит следующий буфер,открываем опять bass поток ,и при закрытии и открытии звук прерывается, а как одновременно писать и считывать данные из потока ,я не знаю, пробовал через waweout , тоже работает но wawe out зависает ,особенно если сворачиваешь или разворачиваешь любое окно с браузером несколько раз, перестает воспроизводится звук. С bass.dll работает не подвисает , как сделать что бы нормально звук воспроизводился пока не знаю может кто что подскажет.



Код:
//открываем поток для воспроизведения ,так как STREAMPROC_PUSH принимает данные из 
//потока, но принимает данные в формате Wav, определим что нужно принимать данные mp3
//может и неправильно(может ошибка закралась тут)
Chan:=  BASS_StreamCreate(44100, 2,BASS_CTYPE_STREAM_MP3, STREAMPROC_PUSH, nil);
BASS_ChannelPlay(chan, False);
BASS_ChannelSetAttribute(chan,BASS_ATTRIB_VOL,1);



procedure TBSTH.outbuf( buf:pbytearray;  len:integer);
var
i,n:integer;
Buffer: array[0..65534] of Byte;
stream:tmemorystream;
Chan1,chan2: HSTREAM;
begin

stream:=tmemorystream.Create;
stream.Write(@Buf[0],len);

if chan1<>0 then
begin
BASS_StreamFree(chan1);
chan1:=0;
end;



chan1:=BASS_StreamCreateFile(True, stream.Memory, 0,stream.Size ,0);
BASS_ChannelSetAttribute(chan1,BASS_ATTRIB_VOL,1);
BASS_ChannelPlay(chan1, true);

stream.Free;
//FreeMem(stream.Memory);
end;

Получается что воспроизвели memorystream ,закрыли (bass поток),затем по приходу новых данных ,опять открываем (bass поток) , и так каждый раз когда приходят данные.

Если бы создать MemoryStream размером 655000 кб. , в него записывать данные ,а потоком bass считывать его по кругу.
т.е. не создавать каждый раз поток(memorystream), а создать его 1-раз,открыть (поток bass) 1-раз, а писать и считывать с одного потока(MemoryStream).

Пробовал с BASS_STREAM_DECODE ,тоже самое звук прерывается. Как сделать ума не приложу , может что кто подскажет.

Спасибо.

Последний раз редактировалось Alex11223; 02.01.2017 в 14:45.
АНАТОЛИЙ249 вне форума Ответить с цитированием
Старый 02.01.2017, 12:03   #2
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

Посмотрите здесь
http://www.programmersforum.ru/showthread.php?t=280127
http://www.programmersforum.ru/showthread.php?t=159534

Звук не должен прерываться видимо неправильно у вас отправка данных идет, нужно отправлять данные от обратного вызова Bass, да и с микрофона насколько я помню mp3 в Bass не сделать, он может только получать данные в mp3, для сжатия звука с микрофона лучше через wawe out он может в кодеке GSM делать если конечно нужно это сжатие, в первой ссылке что я написал, есть проект который с gsm кодеком работает в посте #8.
Если ты хочешь файлы mp3 воспроизводить у клиентов синхронно, то тогда лучше кэшировать файлы на клиентах от сервера, а в сервере проверять позицию воспроизведения этих файлов и отправлять клиентам эту информацию, я так делал для радиотрансляции по сети в нужных зданиях чтобы одновременно все играло в этих зданиях, звук получился качественный ведь кэшь был полноценного файла. У меня со списка воспроизведения на сервере постепенно шел кэшь за воспроизводимым файлом следующего файла.

Последний раз редактировалось Aliens_wolfs; 02.01.2017 в 12:45.
Aliens_wolfs вне форума Ответить с цитированием
Старый 02.01.2017, 13:14   #3
АНАТОЛИЙ249
Пользователь
 
Регистрация: 05.02.2007
Сообщений: 91
По умолчанию

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

Отправлять данные в gsm или Wave ,качество плохое да и размер отправляемых данных большой. данные mp3(44100,128кб/с,2 канала)-размер 1минута 450кб.
Wave 1-минута 8мб.

Может есть Stream в который одновременно и писать и данные считывать можно ?

для вещания mp3 файлов я программу написал на моем сайте http://telecentor.ucoz.ru -> каталог файлов.

нет я пытаюсь написать голосовой чат с конференцией. Можно попробовать прикрутить
VLC библиотеку( paslibVLCPlayerUnit ). тогда можно будет звук и видео отправлять сжатое
одним потоком. но пока не разбирался еще. Пока с этим бы разобраться.

Спасибо за помощь и ответы.

Последний раз редактировалось АНАТОЛИЙ249; 02.01.2017 в 13:23.
АНАТОЛИЙ249 вне форума Ответить с цитированием
Старый 02.01.2017, 13:49   #4
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

GSM кодек можно насколько помню настроить на 65кб/c. Для того чтобы помочь покажите код отправки данных по сети, работаете по UDP или TCP? Да и думаю что у вас идет отправка буфера по 2-м каналам может из за этого и прерывание. В общем нужен частичный код по отправке данных тогда будет более мене понятно в чем проблема

Последний раз редактировалось Aliens_wolfs; 02.01.2017 в 14:33.
Aliens_wolfs вне форума Ответить с цитированием
Старый 02.01.2017, 14:37   #5
АНАТОЛИЙ249
Пользователь
 
Регистрация: 05.02.2007
Сообщений: 91
По умолчанию

не передача и прием работает нормально, передаю и принимаю serversocket и clientsocket.

получилось так:заработало.

Создаем глобальный Stream, указываем его размер.


Код:
  Streampotok:=TmemoryStream.Create;
  Streampotok.Size:=655000;
  Streampotok.Position:=0;


procedure TBSTH.outbuf( buf:Pbytearray; len:integer);
var
i,n:integer;
Buffer: array[0..65534] of Byte;
stream:tmemorystream;
Chan1,chan2: HSTREAM;
begin


Streampotok.Write(@Buf[0],len);



if  bollflag=false then
begin
chan1:=BASS_StreamCreateFile(True, Streampotok.Memory, 0,Streampotok.Size ,BASS_SAMPLE_LOOP);
BASS_ChannelSetAttribute(chan1,BASS_ATTRIB_VOL,1);
BASS_ChannelPlay(chan1, false);
bollflag:=true;
end;



if Streampotok.Position>655000 then
begin
Streampotok.Position:=0;
Streampotok.Size:=655000;
end;






end;
Записываем данные в поток и сразу воспроизводим(bass).
если данные записаны больше размера устанавливаем позицию в 0 и size=655000.

Одновременно и пишиться и считывается.

Проблема не в передачи или в приёме , а проблема в том что данные должны воспроизводится буфер друг за дружкой, а так как идет закрытие потока и опять его открывания ,вот эти паузы и были , сейчас работает непрерывно. но есть одно но,
поток воспроизводится с большой задержкой секунд 5, скажешь слово потом услышишь через 5 секунд ,

Будем дальше думать .

Спасибо за помощь и ответы.

Последний раз редактировалось Alex11223; 02.01.2017 в 14:45.
АНАТОЛИЙ249 вне форума Ответить с цитированием
Старый 02.01.2017, 14:45   #6
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
Сообщение от АНАТОЛИЙ249 Посмотреть сообщение
Streampotok
масло масляное?


Цитата:
Сообщение от АНАТОЛИЙ249 Посмотреть сообщение
но есть одно но,
поток воспроизводится с большой задержкой секунд 5, скажешь слово потом услышишь через 5 секунд
используйте отладчик или вывод в лог чтобы понять на каком этапе происходит задержка.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 02.01.2017, 14:54   #7
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

Что то у тебя на мудрено, там даже Stream ненужен
вот рабочий код без задержки 400 кб/c

Код:
var
chanPlay, ChanMic: Dword;

// от сюда делаешь передачу по сети звука тут же и воспроизведение его
function RecordingCallback(hChan: HRECORD; buffer: Pointer; Size, user: DWord):
 boolean; stdcall;
begin
 BASS_StreamPutData(chanPlay, Buffer, Size);
 BASS_ChannelPlay(chanPlay, false);
end;


//Включаем снятие с микрофона звука и воспроизведения его
procedure TForm1.Button1Click(Sender: TObject);
begin
BASS_RecordInit(-1);
chanMic:=BASS_RecordStart(8000, 2, BASS_CTYPE_STREAM_MP3, @RecordingCallback, nil);
chanPlay:= BASS_StreamCreate(8000, 2, BASS_CTYPE_STREAM_MP3, STREAMPROC_PUSH, nil);
end;


//Закрываем все
procedure TForm1.Button2Click(Sender: TObject);
begin
BASS_RecordFree;
BASS_StreamFree(chanPlay);
BASS_StreamFree(chanMic);
end;
Но мне все равно кажеться что воспроизведение идет не mp3

Последний раз редактировалось Aliens_wolfs; 02.01.2017 в 15:04.
Aliens_wolfs вне форума Ответить с цитированием
Старый 02.01.2017, 14:55   #8
АНАТОЛИЙ249
Пользователь
 
Регистрация: 05.02.2007
Сообщений: 91
По умолчанию

Надо с наверно отслеживать позицию записи в Streampotok и позицию в bass при проигрывании этого Streampotok.

Или у кого есть другие наработки по воспроизведению MP3 из буфера или потока другими средствами?

WAveOut Работает нормально без перерывов,но если свернуть и развернуть окно браузера ,WAveOut останавливается и дальше не воспроизводит буфер который приходит.

если бы WAveOut не затыкался бы тогда было бы все отлично, вот и думаю перейти на BASS, может другие средства есть ?
Делал как интернет радио , там тоже работает хорошо но задержка большая секунд 5, пока забуферезируется .

у меня размер 1минута 450кб.

Спасибо за ответы и помощь.

Последний раз редактировалось АНАТОЛИЙ249; 02.01.2017 в 14:58.
АНАТОЛИЙ249 вне форума Ответить с цитированием
Старый 02.01.2017, 15:05   #9
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

Посмотри код выше рабочий 400кб/c может что найдете в нем полезного

Со Stream такая скорость как у тебя темболее будет задержка ведь у тебя кэшь идет а потом отправка

Последний раз редактировалось Aliens_wolfs; 02.01.2017 в 15:13.
Aliens_wolfs вне форума Ответить с цитированием
Старый 02.01.2017, 15:52   #10
АНАТОЛИЙ249
Пользователь
 
Регистрация: 05.02.2007
Сообщений: 91
По умолчанию

Можно конечно конвертировать обратно в формат wav, а затем отправить в BASS_StreamPutData(chanPlay, Buffer, Size);

BASS_StreamPutData-воспроизводит только звуковой формат не сжатый.

Mожет у кого есть наработки конвертера mp3 to wav на лету ?
Находил только из файла в файл, а мне нужно из буфера или stream в буфер или stream.

Cпасибо за помощь буду думать
АНАТОЛИЙ249 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
[РЕШЕНО] bass.dll, Программа получает мп3 файл с сервера и воспроизводит его, как его сохранить в файл? NEoMASTERR Общие вопросы Delphi 0 25.01.2016 11:30
BASS.DLL и захват потока. Twister901 Visual C++ 1 15.01.2013 10:54
Bass.dll не воспроизводит m3u demiancz Мультимедиа в Delphi 19 30.10.2012 08:46
bass.dll Скорость мать его потока... Дворник Мультимедиа в Delphi 5 24.08.2010 09:37
микшер на два потока в проигрывателе музыки. проигрыватель сделан на основе библиотеки Bass.dll D-fens Мультимедиа в Delphi 4 08.06.2007 20:36