Можно ли отправить поток из данных BLOB-объектов в базе данных в PlaySound (MMSystem) вместо указания имени файла?

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

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

На данный момент у меня есть

    String file = frmMDI->dlg->InitialDir + "\\sounds\\" + "ObservationDateTimeField.wav";
    speech->Send(file);

Что это делает, так это высказывает инструкции о том, что ожидается в поле, когда он получил фокус, он работает нормально, как есть, но хотел бы получить wav из базы данных, чтобы через usb распространялось минимальное количество файлов.

в методе OnEnter речь - это настраиваемый элемент управления, который управляет моими потребностями, просто требование PlaySound(...) для файлов .wav, другие элементы управления определяют, как и когда отправлять инструкции.

Обновлено: а добавить скриншот окна наблюдения

Скриншот основной записи наблюдения

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

Как мне поступить, если это возможно?

У меня не было времени попробовать слишком много вещей, таких как отправка потока вместо файла, воспроизведение звука отлично работает из звукового файла .wav

Редактировать: спасибо Spektre за время и код, очень признателен.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
137
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

PlaySound() не может воспроизводить звук из потока. Он может воспроизводиться из файла, блока памяти или ресурса EXE/DLL.

Я бы не рекомендовал хранить аудио WAV в больших двоичных объектах базы данных. Вместо этого используйте файлы или ресурсы. Но если вам необходимо использовать базу данных, вы можете использовать метод TDataSet::CreateBlobStream(), чтобы получить доступ только для чтения TStream для доступа к данным большого двоичного объекта, а затем вы можете Read() эти данные в выделенный буфер памяти или CopyFrom() в TMemoryStream, а затем вы можете PlaySound() играть из памяти этого буфера/потока.

Если вам действительно нужно воспроизводить потоковое аудио, вам придется использовать waveOutOpen() / waveOutPrepareHeader() / waveOutWrite() напрямую или использовать более современные API, такие как DirectSound или XAudio2. вместо этого.

Спасибо за ваш ответ, из-за моей непосредственной ситуации, вы можете показать, как я мог бы использовать эти методы, у меня действительно нет времени, чтобы провести собственное исследование по этому вопросу, если лучше всего использовать PlaySound из файла, тогда это нужно будет сделать, ура

OutOfTime 11.02.2023 23:41

StackOverflow — это сайт вопросов и ответов, а не сервис написания кода.

Remy Lebeau 12.02.2023 00:07

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

OutOfTime 12.02.2023 00:51
Ответ принят как подходящий

по моему опыту, WAVEIN / WAVEOUT - лучший звуковой API для этой цели ... DirectSound глючит (был) с очень большой задержкой, поэтому я прекратил его использовать много лет назад ...

Вот моя древняя библиотека C++, которую я изначально написал для своих приложений осциллографа, спектрального анализатора, генератора сигналов, но использую ее везде, даже в своем эмуляторе ZXSpectrum:

волна.ч:

//---------------------------------------------------------------------------
//--- WAVE IN/OUT class ver: 4.02 -------------------------------------------
//---------------------------------------------------------------------------
#ifndef _waveout_h
#define _waveout_h
//---------------------------------------------------------------------------
#include <mmsystem.h>
#include "fifo.h"
#include "lock.h"
//---------------------------------------------------------------------------
void CALLBACK wave_in_event(HWAVEIN hw,UINT msg,DWORD inst,DWORD p1,DWORD p2);
void CALLBACK wave_out_event(HWAVEOUT hw,UINT msg,DWORD inst,DWORD p1,DWORD p2);
//---------------------------------------------------------------------------
class wave_in
    {
public:
    bool _init,_fifo;
    FIFO<BYTE> fifo;
    WAVEHDR *hdr;
    HWAVEIN hw;
    WAVEFORMATEX buff_format;
    DWORD buff_size;
    DWORD  freq; WORD chanels,bits,samples,buffers;
    BYTE **buff;
    int adr,num;

    void CALLBACK (*event)(HWAVEIN hw,UINT msg,DWORD inst,DWORD p1,DWORD p2);
//  void (*onreceive)(wave_in *wi,BYTE *data,int size);
    void (__closure *onreceive)(wave_in *wi,BYTE *data,int size);

    wave_in()
        {
        hdr=NULL;
        buff=NULL;
        buffers=0;
        buff_size=0;
        _init=false;
        adr=0;
        num=0;
        event=wave_in_event;
        onreceive=NULL;
        }
    ~wave_in()
        {
        _free();
        }
    wave_in(wave_in& a) { *this=a; }
    wave_in* operator = (const wave_in *a) { *this=*a; return this; }
    //wave_in* operator = (const wave_in &a) { ...copy... return this; }

    void _free()
        {
        adr=0;
        num=0;
        if (_init) { waveInClose(hw); _init=false; }
        #ifdef _mmap_h
        if (buff) for (int i=0;i<buffers;i++) if (buff[i]) mmap_del(buff[i]);
        if (buff) mmap_del(buff);
        if (hdr ) mmap_del(hdr );
        #endif
        if (buff)
            {
            for (int i=0;i<buffers;i++) if (buff[i]) delete[] buff[i];
            delete[] buff;
            buff=NULL;
            }
        if (hdr) { delete[] hdr; hdr=NULL; }
        }
    void init(DWORD _freq,WORD _chanels,WORD _bits,WORD _samples,WORD _buffers=5)
        {
        int i,ret;
        _free();
        buffers=_buffers;
        if (buffers<1) buffers=1;
        hdr=new WAVEHDR[buffers];
        buff=new BYTE*[buffers];
        #ifdef _mmap_h
        if (hdr ) mmap_new(hdr ,buffers*sizeof(WAVEHDR));
        if (buff) mmap_new(buff,buffers*sizeof(BYTE*));
        #endif
        freq    =_freq;
        chanels =_chanels;
        bits    =_bits;
        samples =_samples;
        buff_size=(chanels*bits*samples)>>3;
        samples=(buff_size<<3)/(chanels*bits);

        for (i=0;i<buffers;i++) buff[i]=new BYTE[buff_size];
        #ifdef _mmap_h
        for (i=0;i<buffers;i++) if (buff[i]) mmap_new(buff[i],buff_size);
        #endif

        buff_format.wFormatTag      =WAVE_FORMAT_PCM;       // set buffer format
        buff_format.nChannels       =chanels;
        buff_format.nSamplesPerSec  =freq;
        buff_format.wBitsPerSample  =bits;
        buff_format.cbSize          =0;
        buff_format.nAvgBytesPerSec =(freq*chanels*bits)>>3;
        buff_format.nBlockAlign     =(chanels*bits)>>3;
        if (event) ret=waveInOpen(&hw,WAVE_MAPPER,&buff_format,(DWORD_PTR)event,(DWORD_PTR)this,CALLBACK_FUNCTION);
        else       ret=waveInOpen(&hw,WAVE_MAPPER,&buff_format,0,0,CALLBACK_NULL);
        if (ret!=MMSYSERR_NOERROR)
            {
//          waveInGetErrorText(ret,err,255);
            return;
            }
        WAVEHDR hdr0;
        hdr0.dwBufferLength=buff_size;
        hdr0.dwUser=0;
        hdr0.dwFlags=0;
        hdr0.dwLoops=0;
        hdr0.lpNext=NULL;
        for (i=0;i<buffers;i++)
            {
            hdr[i]=hdr0;
            hdr[i].lpData=buff[i];
            }
        _init=true;
        }
    void add()
        {
        if (!_init) return;
        int i,ret;
        BYTE *p;
        p=buff[adr];
        ret=waveInPrepareHeader(hw,&hdr[adr],sizeof(WAVEHDR));
        if (ret!=MMSYSERR_NOERROR)
            {
//          waveInGetErrorText(ret,err,255);
            return;
            }
        waveInAddBuffer(hw,&hdr[adr],sizeof(WAVEHDR));
        if (ret!=MMSYSERR_NOERROR)
            {
//          waveInGetErrorText(ret,err,255);
            return;
            }
        adr++;
        if (adr>=buffers) adr=0;
        num++;
        }
    void start()
        {
        if (!_init) return;
        while (num<buffers) add();
        waveInStart(hw);
        }
    void stop()
        {
        if (!_init) return;
        waveInStop(hw);
        }
    };
//---------------------------------------------------------------------------
class wave_out:public multi_lock
    {
public:
    bool _init,_fifo;
    FIFO<BYTE> fifo;
    WAVEHDR *hdr;
    HWAVEOUT hw;
    WAVEFORMATEX buff_format;
    DWORD buff_size;
    DWORD  freq; WORD chanels,bits,samples,buffers;
    BYTE **buff;
    int adr,num,err;

    void CALLBACK (*event)(HWAVEOUT hw,UINT msg,DWORD inst,DWORD p1,DWORD p2);

    wave_out()
        {
        hdr=NULL;
        buff=NULL;
        buffers=0;
        buff_size=0;
        _init=false;
        adr=0;
        num=0;
        err=0;
        event=wave_out_event;
        }
    ~wave_out()
        {
        _free();
        }
    wave_out(wave_out& a)   { *this=a; }
    wave_out* operator = (const wave_out *a) { *this=*a; return this; }
    //wave_out* operator = (const wave_out &a) { ...copy... return this; }
    void _free()
        {
        adr=0;
        num=0;
        if (_init) { waveOutClose(hw); _init=false; }
        #ifdef _mmap_h
        if (buff) for (int i=0;i<buffers;i++) if (buff[i]) mmap_del(buff[i]);
        if (buff) mmap_del(buff);
        if (hdr ) mmap_del(hdr );
        #endif
        if (buff)
            {
            for (int i=0;i<buffers;i++) if (buff[i]) delete[] buff[i];
            delete[] buff;
            buff=NULL;
            }
        if (hdr) { delete[] hdr; hdr=NULL; }
        }
    void init(DWORD _freq,WORD _chanels,WORD _bits,WORD _samples,WORD _buffers=10)
        {
        int i,ret;
        _free();
        buffers=_buffers;
        if (buffers<1) buffers=1;
        hdr=new WAVEHDR[buffers];
        buff=new BYTE*[buffers];
        #ifdef _mmap_h
        if (hdr ) mmap_new(hdr ,buffers*sizeof(WAVEHDR));
        if (buff) mmap_new(buff,buffers*sizeof(BYTE*));
        #endif

        freq    =_freq;
        chanels =_chanels;
        bits    =_bits;
        samples =_samples;
        buff_size=(chanels*bits*samples)>>3;
        samples=(buff_size<<3)/(chanels*bits);

        for (i=0;i<buffers;i++) buff[i]=new BYTE[buff_size];
        #ifdef _mmap_h
        for (i=0;i<buffers;i++) if (buff[i]) mmap_new(buff[i],buff_size);
        #endif

        buff_format.wFormatTag      =WAVE_FORMAT_PCM;       // set buffer format
        buff_format.nChannels       =chanels;
        buff_format.nSamplesPerSec  =freq;
        buff_format.wBitsPerSample  =bits;
        buff_format.cbSize          =0;
        buff_format.nAvgBytesPerSec =(freq*chanels*bits)>>3;
        buff_format.nBlockAlign     =(chanels*bits)>>3;
        if (event) ret=waveOutOpen(&hw,WAVE_MAPPER,&buff_format,(DWORD_PTR)event,(DWORD_PTR)this,CALLBACK_FUNCTION);
        else       ret=waveOutOpen(&hw,WAVE_MAPPER,&buff_format,0,0,CALLBACK_NULL);
        if (ret!=MMSYSERR_NOERROR)
            {
//          waveOutGetErrorText(ret,err,255);
            return;
            }
        WAVEHDR hdr0;
        hdr0.dwBufferLength=buff_size;
        hdr0.dwUser=0;
        hdr0.dwFlags=WHDR_INQUEUE;
        hdr0.dwLoops=0;
        hdr0.lpNext=NULL;
        for (i=0;i<buffers;i++)
            {
            hdr[i]=hdr0;
            hdr[i].lpData=buff[i];
            }
        _init=true;
        }
    void send(BYTE *data)
        {
        if (!_init) return;
        lock();

        if (num>buffers)
            {
            err++;
            adr=0;
            num=0;
            }

        DWORD i;
        int ret;
        BYTE *p;
        p=buff[adr];
        for (i=0;i<buff_size;i++) p[i]=data[i];
        ret=waveOutPrepareHeader(hw,&hdr[adr],sizeof(WAVEHDR));
        if (ret!=MMSYSERR_NOERROR)
            {
//          waveOutGetErrorText(ret,err,255);
            unlock();
            return;
            }
        waveOutWrite(hw,&hdr[adr],sizeof(WAVEHDR));
        if (ret!=MMSYSERR_NOERROR)
            {
//          waveOutGetErrorText(ret,err,255);
            unlock();
            return;
            }
        adr++;
        if (adr>=buffers) adr=0;
        num++;
        unlock();
        }
    void stop()
        {
        waveOutReset(hw);
        }
    };
//---------------------------------------------------------------------------
void CALLBACK wave_in_event(HWAVEIN hw,UINT msg,DWORD inst,DWORD p1,DWORD p2)
    {
    wave_in *w=(wave_in*)(void*)(DWORD_PTR)inst;
    if (w==NULL) return;
    if (msg==WIM_OPEN);             // open wave HW
    if (msg==WIM_DATA)              // wave data send done
        {
        int adr0=w->adr-w->num;
        while (adr0>=w->buffers) adr0-=w->buffers;
        while (adr0<          0) adr0+=w->buffers;
        if (w->onreceive) w->onreceive(w,w->buff[adr0],w->buff_size);
        w->num--;
        }                        
    if (msg==WIM_CLOSE);            // close wave HW
    }
//---------------------------------------------------------------------------
void CALLBACK wave_out_event(HWAVEOUT hw,UINT msg,DWORD inst,DWORD p1,DWORD p2)
    {
    wave_out *w=(wave_out*)(void*)(DWORD_PTR)inst;
    if (w==NULL) return;
    w->lock();
    if (msg==WOM_OPEN);             // open wave HW
    if (msg==WOM_DONE) w->num--;    // wave data send done
    if (msg==WOM_CLOSE);            // close wave HW
    w->unlock();
    }
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------

поддержка файла lock.h:

//---------------------------------------------------------------------------
//--- Multithread lock class ver 1.00 ---------------------------------------
//---------------------------------------------------------------------------
#ifndef _lock_h
#define _lock_h
//---------------------------------------------------------------------------
class single_lock
    {
public:
    CRITICAL_SECTION hnd;

    single_lock()                                   { InitializeCriticalSectionAndSpinCount(&hnd,0x00000400); }
    ~single_lock()                                  { DeleteCriticalSection(&hnd); }
    single_lock(single_lock& a)                     { *this=a; }
    single_lock* operator = (const single_lock *a)  { *this=*a; return this; }
//  single_lock* operator = (const single_lock &a)  { **** }

    // thread safe functions
    inline void lock()      { EnterCriticalSection(&hnd); }
    inline void unlock()    { LeaveCriticalSection(&hnd); }
    };
//---------------------------------------------------------------------------
const int _multi_lock_size=16;                      // max number of simultanious access
class multi_lock
    {
public:
    CRITICAL_SECTION hnd;
    CRITICAL_SECTION dat[_multi_lock_size];
    DWORD adr0,adr1,siz;

    multi_lock()                                    { InitializeCriticalSectionAndSpinCount(&hnd,0x00000400); for(int i=0;i<_multi_lock_size;i++) InitializeCriticalSectionAndSpinCount(&dat[i],0x00000400); adr0=0; adr1=0; siz=0; }
    ~multi_lock()                                   { DeleteCriticalSection(&hnd); for(int i=0;i<_multi_lock_size;i++) DeleteCriticalSection(&dat[i]); }
    multi_lock(multi_lock& a)                       { *this=a; }
    multi_lock* operator = (const multi_lock *a)    { *this=*a; return this; }
//  multi_lock* operator = (const multi_lock &a)    { **** }

    // thread safe functions
    inline void lock()
        {
        EnterCriticalSection(&hnd);
        if (siz<_multi_lock_size)
            {
            siz++;
            EnterCriticalSection(&dat[adr1]);
            adr1++; if (adr1>=_multi_lock_size) adr1=0;
            }
//      else error();
        LeaveCriticalSection(&hnd);
        }
    inline void unlock()
        {
        EnterCriticalSection(&hnd);
        if (siz>0)
            {
            siz--;
            LeaveCriticalSection(&dat[adr0]);
            adr0++; if (adr0>=_multi_lock_size) adr0=0;
            }
//      else error();
        LeaveCriticalSection(&hnd);
        }
    };
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------

файл поддержки FIFO.h:

//---------------------------------------------------------------------------
//--- FIFO template class ver 2.08 ------------------------------------------
//---------------------------------------------------------------------------
#ifndef _fifo_h
#define _fifo_h
//---------------------------------------------------------------------------
//static bool _enable_fifo_debug=false;
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
template <class T> class FIFO
    {
public:
    T *dat;
    int adr0,adr1,size;
    CRITICAL_SECTION lock;

    FIFO()                          { dat=NULL; InitializeCriticalSectionAndSpinCount(&lock,0x00000400); alloc(16); }
    ~FIFO()                         { _free(); DeleteCriticalSection(&lock); }
    FIFO(FIFO& a)                   { *this=a; }
    FIFO* operator = (const FIFO *a){ *this=*a; return this; }
    FIFO* operator = (const FIFO &a){ EnterCriticalSection(&a.lock); EnterCriticalSection(&lock); _alloc(a.size); adr0=a.adr0; adr1=a.adr1; for (int i=0;i<size;i++) dat[i]=a.dat[i]; LeaveCriticalSection(&lock); LeaveCriticalSection(&a.lock); return this; }

    // already locked functions
    inline int  _adr_inc(int a)  volatile { a++; if (a>=size) a=0; return a; }
    inline int  _adr_dec(int a)  volatile { if (a!=adr0) a--; if (a<0) a=size-1; return a; }
    inline void _alloc(int _size)volatile { if (dat) delete[] dat; dat=NULL; size=_size; adr0=0; adr1=0; dat=new T[size]; if (dat==NULL) size=0; _reset(); }
    inline void _free()          volatile { if (dat) delete[] dat; dat=NULL; size=    0; adr0=0; adr1=0; }
    inline void _reset()         volatile { adr0=0; adr1=0; }
    inline void _in(T x)         volatile { if (_is_full()) return; dat[adr1]=x; adr1=_adr_inc(adr1); }
    inline T     _out()          volatile { if (_is_empty()){ T null; return null; } T x=dat[adr0]; adr0=_adr_inc(adr0); return x; }
    inline T     _peek_first()   volatile { if (_is_empty()){ T null; return null; } T x=dat[adr0]; return x; }
    inline T     _peek_last()    volatile { if (_is_empty()){ T null; return null; } int a=_adr_dec(adr1); T x=dat[a]; return x; }
    inline bool _is_empty()      volatile { bool ret=(adr0==adr1); return ret; }
    inline bool _is_full()       volatile { int a=_adr_inc(adr1); bool ret=(a==adr0); return ret; }
    inline int  _get_size()      volatile { if (_is_empty()) return 0; if (_is_full()) return size; if (adr0<adr1) return adr1-adr0; else return size+adr1-adr0; }

    // thread safe functions
    void _lock()            volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock); }
    void _unlock()          volatile { LeaveCriticalSection((CRITICAL_SECTION*)&lock); }
    void alloc(int _size)   volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock);        _alloc(_size); LeaveCriticalSection((CRITICAL_SECTION*)&lock); }
    void reset()            volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock);        _reset();      LeaveCriticalSection((CRITICAL_SECTION*)&lock); }
    void in(T x)            volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock);        _in(x);        LeaveCriticalSection((CRITICAL_SECTION*)&lock); }
    T    out()              volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock); T    x=_out();        LeaveCriticalSection((CRITICAL_SECTION*)&lock); return x; }
    T    peek_first()       volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock); T    x=_peek_first(); LeaveCriticalSection((CRITICAL_SECTION*)&lock); return x; }
    T    peek_last()        volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock); T    x=_peek_last();  LeaveCriticalSection((CRITICAL_SECTION*)&lock); return x; }
    bool is_empty()         volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock); bool x=_is_empty();   LeaveCriticalSection((CRITICAL_SECTION*)&lock); return x; }
    bool is_full()          volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock); bool x=_is_full();    LeaveCriticalSection((CRITICAL_SECTION*)&lock); return x; }
    int  get_size()         volatile { EnterCriticalSection((CRITICAL_SECTION*)&lock); int  x=_get_size();   LeaveCriticalSection((CRITICAL_SECTION*)&lock); return x; }
    };
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

здесь простое использование (извлечено из моего генератора, надеюсь, я ничего не забыл):

// globals and init
const int _size=20*1024;
wave_out wo;
WORD buffer[_size]; // your PCM sound data matching the init operands
wo.init(44100,2,16,_size,10); // sampling_freq,channels,bits,buffer size,buffers

// this in some timer or thread (fast enbough)
while (wo.num<4)
 {
 // here prepare buff[] data 
 wo.send((BYTE*)buff); 
 }

// force to stop on app exit or when needed
wo.stop();

Материал был скомпилирован в BDS2006 C++ Builder, поэтому, если вы используете более новый компилятор, вам может понадобиться настроить некоторые вещи ... еще не было времени портировать это на новый компилятор, поэтому в случае необходимости см. это.

wave_out для воспроизведения звука и wave_in для записи, оба используют предпочтительное звуковое устройство Windows, выбранное в панели управления Windows. Чтобы включить плавное воспроизведение, просто убедитесь, что в звуковой очереди заполнено не менее 4 буферов while (wo.num<4)... иначе могут возникнуть сбои звука

Вам также может понадобиться декодировать файлы WAV, поэтому вот еще одна моя древняя библиотека RIFF.h:

//---------------------------------------------------------------------------
//--- RIFF WAVE format: 1.01 ------------------------------------------------
//---------------------------------------------------------------------------
#ifndef _RIFF_h
#define _RIFF_h
//---------------------------------------------------------------------------
// 8bit PCM is unsigned
// 16bit PCM is signed 2'os complement little endian (big endian is RIFX)
//---------------------------------------------------------------------------
struct _wave_chunk
    {
    DWORD ids;
    DWORD len;
    _wave_chunk(){ ids='    '; len=0; }
    _wave_chunk(_wave_chunk& a){ *this=a; }; ~_wave_chunk(){}; _wave_chunk* operator = (const _wave_chunk *a) { *this=*a; return this; }; /*_wave_chunk* operator = (const _wave_chunk &a) { ...copy... return this; };*/
    };
struct _wave_hdr
    {
    DWORD ids;      // "RIFF"
    DWORD len;
    DWORD tps;      // "WAVE"
    _wave_hdr(){ ids='FFIR'; len=0; tps='EVAW'; }
    _wave_hdr(_wave_hdr& a){ *this=a; }; ~_wave_hdr(){}; _wave_hdr* operator = (const _wave_hdr *a) { *this=*a; return this; }; /*_wave_hdr* operator = (const _wave_hdr &a) { ...copy... return this; };*/
    };
struct _wave_fmt
    {
    DWORD ids;      // "fmt "
    DWORD len;      // 16,18,40
    WORD  format;   // 1 = PCM linear quantization
/*                      0x0001  WAVE_FORMAT_PCM PCM
                        0x0003  WAVE_FORMAT_IEEE_FLOAT  IEEE float
                        0x0006  WAVE_FORMAT_ALAW    8-bit ITU-T G.711 A-law
                        0x0007  WAVE_FORMAT_MULAW   8-bit ITU-T G.711 µ-law
                        0xFFFE  WAVE_FORMAT_EXTENSIBLE  Determined by SubFormat */
    WORD  chanels;
    DWORD samplerate;
    DWORD byterate;
    WORD  blockalign;
    WORD  bits;
    WORD  ext_len;  // extension length 0,22
    WORD  ext_validbits;
    DWORD ext_channelmask;
    BYTE  ext_subformat[16];
    _wave_fmt(){ ids=' tmf'; len=16; format=1; chanels=1; samplerate=44100; bits=8; ext_len=0; ext_validbits=0; ext_channelmask=0; for (int i=0;i<16;i++) ext_subformat[i]=0; compute(); }
    _wave_fmt(_wave_fmt& a){ *this=a; }; ~_wave_fmt(){}; _wave_fmt* operator = (const _wave_fmt *a) { *this=*a; return this; }; /*_wave_fmt* operator = (const _wave_fmt &a) { ...copy... return this; };*/
    void compute()
        {
        byterate=(chanels*samplerate*bits)/8;
        blockalign=(chanels*bits)/8;
        }
    };
struct _wave_dat
    {
    DWORD ids;      // "data"
    DWORD len;
    _wave_dat(){ ids='atad'; len=0; }
    _wave_dat(_wave_dat& a){ *this=a; }; ~_wave_dat(){}; _wave_dat* operator = (const _wave_dat *a) { *this=*a; return this; }; /*_wave_dat* operator = (const _wave_dat &a) { ...copy... return this; };*/
    };
//---------------------------------------------------------------------------
class wave
    {
public:
    AnsiString name;
    int hnd;
    bool readonly;
    _wave_hdr hdr;
    _wave_fmt fmt;
    _wave_dat dat;

    wave();
    ~wave();
    void create(AnsiString _name);
    void write(BYTE *data,DWORD size);

    bool open(AnsiString _name);
    DWORD read(BYTE *data,DWORD size);
    void close();
    };
//---------------------------------------------------------------------------
wave::wave()
    {
    name=0;
    hnd=-1;
    readonly=true;
    }
//---------------------------------------------------------------------------
wave::~wave()
    {
    close();
    }
//---------------------------------------------------------------------------
void wave::create(AnsiString _name)
    {
    close();
    readonly=true;
//  hdr=_wave_hdr();
//  fmt=_wave_fmt();
//  dat=_wave_dat();
    hdr.len=sizeof(hdr)-8;
    dat.len=0;
    fmt.compute();
    name=_name;
    hnd=FileCreate(name);
    if (hnd<0) return;
    FileWrite(hnd,&hdr,sizeof(hdr));
    FileWrite(hnd,&fmt,fmt.len+8);
    FileWrite(hnd,&dat,sizeof(dat));
    readonly=false;
    }
//---------------------------------------------------------------------------
bool wave::open(AnsiString _name)
    {
    close();
    readonly=true;
    name=_name;
    hnd=FileOpen(name,fmOpenRead);
    if (hnd<0) return false;
    if (FileRead(hnd,&hdr,sizeof(hdr))<sizeof(hdr)){ close(); return false; }
    if (hdr.ids!='FFIR') return false;
    if (hdr.tps!='EVAW') return false;
    _wave_chunk chk;
    DWORD sz=sizeof(chk),l;
    for(;;)
        {
        if (FileRead(hnd,&chk,sz)<sz){ close(); return false; }
            if (chk.ids==' tmf')
            {
            fmt.ids=chk.ids;
            fmt.len=chk.len;
            if (FileRead(hnd,((BYTE*)&fmt)+sz,chk.len)<chk.len){ close(); return false; }
            }
        else if (chk.ids=='atad')
            {
            dat.ids=chk.ids;
            dat.len=chk.len;
            return true;
            }
        else FileSeek(hnd,int(chk.len),1);
        }
    }
//---------------------------------------------------------------------------
void wave::write(BYTE *data,DWORD size)
    {
    if (hnd<0) return;
    hdr.len+=size;
    dat.len+=size;
    if (!readonly) FileWrite(hnd,data,size);
    }
//---------------------------------------------------------------------------
DWORD wave::read(BYTE *data,DWORD size)
    {
    if (hnd<0) return 0;
    return FileRead(hnd,data,size);
    }
//---------------------------------------------------------------------------
void wave::close()
    {
    name = "";
    if (hnd<0) return;
    FileSeek(hnd,0,0);
    if (!readonly) FileWrite(hnd,&hdr,sizeof(hdr));
    FileClose(hnd);
    hnd=-1;
    }
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------

И использование:

// globals
wave wav;
wave_out wo;
BYTE *buff;

// init
wav.open("tetris2.wav"); // any file ...
wo.init(wav.fmt.samplerate,wav.fmt.chanels,wav.fmt.bits,dt*wav.fmt.samplerate/1000,10);
buff=new BYTE[wo.buff_size];

// timer 20ms ...
while (wo.num<4)
            {
            wav.read(buff,wo.buff_size);
            wo.send(buff);
            }

// exit
wo.stop();
wav.close();
delete[] buff;

wav.read(...) возвращает количество прочитанных БАЙТОВ, поэтому, как только он достигает размера буфера меньше или даже равен нулю, это означает, что вы уже находитесь в конце волнового файла ... Теперь, когда у вас будет wav в памяти, просто перепишите доступ к файлу для доступа к памяти .. .

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

OutOfTime 12.02.2023 21:10

Другие вопросы по теме