Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[52.14.126.74] |
|
Сообщ.
#1
,
|
|
|
http://msdn.microsoft.com/en-us/library/wi...6(v=vs.85).aspx
Цитата Unless the device is paused by calling the waveOutPause function, playback begins when the first data block is sent to the device. Подскажите что там написано. 1 Когда устройство стоит на паузе, вызов waveOutWrite записывает буфер в очередь не запуская воспроизведение (устройство остается на паузе) 2 Когда устройство стоит на паузе, вызов waveOutWrite запускает воспроизведение буфера. И у меня еще один вопрос про ошибку: waveOutWrite возвращает десятичное значение 33. Я нашел описание ошибок только до 21. Как мне узнать описание этой ошибки? |
Сообщ.
#2
,
|
|
|
Цитата Суровый @ "Хотя устройство и находится на паузе, в ожидании завершения выхода из функции waveOutWrite, воспроизведение начнётся как токмо первые данные придут в него, в устройство." Подскажите что там написано. Добавлено Цитата Суровый @ Наверное, там якобы-битовые разделы:waveOutWrite возвращает десятичное значение 33. Я нашел описание ошибок только до 21. Как мне узнать описание этой ошибки? #define MMSYSERR_BASE 0 #define WAVERR_BASE 32 #define MIDIERR_BASE 64 #define TIMERR_BASE 96 #define JOYERR_BASE 160 #define MCIERR_BASE 256 #define MIXERR_BASE 1024 #define MMSYSERR_ERROR (MMSYSERR_BASE + 1) /* unspecified error */ Добавлено Цитата Славян @ Тьфу, виноват, слово 'якобы' надо зачеркнуть. Как-то мой мозг быстро не смог поделить 160 на 32, а оказывается делится! Всё нормально: первые 5 бит - на детали ошибки, старшие - на раздел/суть оной. там якобы-битовые разделы |
Сообщ.
#3
,
|
|
|
Цитата Подскажите что там написано. Что если устройство не "поставлено на паузу" вызовом соотвествующей функции, то воспроизведение начинается сразу после того, как устроству передан блок данных. |
Сообщ.
#4
,
|
|
|
Постовил я 33-ю ошибку на игнор, и всё заработало как надо.
Тут Славян подсказал что надо смотреть WAVERR_ а не MMSYSERR_. И действительно оказалось, что это "Сейчас что-то уже играет". Собственно что из этого: Цитата Славян @ "Хотя устройство и находится на паузе, в ожидании завершения выхода из функции waveOutWrite, воспроизведение начнётся как токмо первые данные придут в него, в устройство." вытекает 1 или 2? Добавлено Prince, ясно спасибо. |
Сообщ.
#5
,
|
|
|
Цитата Суровый @ Увы, я не понял вопроса. Собственно что из этого: ... вытекает 1 или 2? |
Сообщ.
#6
,
|
|
|
Вопросы решены.
Славян, вытекает 1 (усройство остается на паузе). Плюсик я тебе завтра поставлю. |
Сообщ.
#7
,
|
|
|
Цитата Постовил я 33-ю ошибку на игнор, и всё заработало как надо. Цитата Вопросы решены. |
Сообщ.
#8
,
|
|
|
Цитата Суровый @ Плюсик я тебе завтра поставлю. Э-э-э Забейте. Зачтём сегодняшний, политический, как два по поллитра: 1=2*0,5 |
Сообщ.
#9
,
|
|
|
Prince, 33 это по сути не ошибка, а сообщение, что что-то уже(еще) игрет
Добавлено #define WAVERR_STILLPLAYING (WAVERR_BASE + 1) /* still something playing */ |
Сообщ.
#10
,
|
|
|
Цитата Prince @ А вы думали! Силён наш Суровый, силён! Цитата Постовил я 33-ю ошибку на игнор, и всё заработало как надо. Цитата Вопросы решены. |
Сообщ.
#11
,
|
|
|
Цитата это по сути не ошибка Точно-точно? Майкрософт говорит, что waveoutwrite вообще такое не умеет возвращать в качестве результата, хотя может у меня sdk устаревший. В любом случае, имхо, стоит разобраться, что оно означает, это сообщение, и почему вылазит. Может, покажете послеовательность действий? |
Сообщ.
#12
,
|
|
|
Цитата Prince @ В любом случае, имхо, стоит разобраться, что оно означает, это сообщение, и почему вылазит. Может, покажете послеовательность действий? Мне не принципиально. Но если интересно то вот: AudioUnit.h //--------------------------------------------------------------------------- #ifndef AudioUnitH #define AudioUnitH // #include "UtilUnit.h" #include "mmsystem.hpp" #include "DataUnit.h" #include <Classes.hpp> // class CPlayer; class CBuffer { private: AudioFmt Fmt; int Size; int Rate; void *WO; char *Buf; WAVEHDR WH[2]; public: CBuffer(AudioFmt aFmt, int aSize, int aRate); ~CBuffer(); void Play(int n); void Pause(); void Restart(); void Reset(); void SetVol(int aVol); CPlayer *pPlayer; int GetBufNum(void *P); void *GetBufPtr(int N); }; class CPlayTh: public TThread { private: CPlayer *Player; HANDLE SignalDone; public: CPlayTh(CPlayer *aPlayer); void __fastcall Execute(); void Done(); }; enum TPlayMsg {PM_DONE_BUF,PM_DONE_FILE}; class CPlayer { private: CBuffer *Buf; CWAVE *Wav; CPlayTh *Th; int nBuf; bool Paused; bool Played; TRTLCriticalSection CS; HWND Wnd; void LoadNextFrame(int nBuf); public: CPlayer(CWAVE *aWav, HWND W=0); ~CPlayer(); void DoneBuf(int n); void __fastcall LoadTh(); void SetPos(int nPos); void SetVol(int aVol); void Play(); void Pause(); }; //--------------------------------------------------------------------------- #endif AudioUnit.cpp //--------------------------------------------------------------------------- #pragma hdrstop #include "AudioUnit.h" #include <mmsystem.hpp> //--------------------------------------------------------------------------- #pragma package(smart_init) void CALLBACK waveOutCallBack(int WO, UINT Msg, CBuffer *P, void *a1, int a2) { if (Msg==WOM_DONE) if (P->pPlayer!=NULL) P->pPlayer->DoneBuf( P->GetBufNum(a1) ); } CBuffer::CBuffer(AudioFmt aFmt, int aSize, int aRate) { Fmt = aFmt; Size = aSize; Rate = aRate; WAVEFORMATEX WF; WF.wFormatTag = WAVE_FORMAT_PCM; WF.nChannels = CannalsFmt(Fmt); WF.nSamplesPerSec = Rate; WF.nAvgBytesPerSec = BytesFmt(Fmt)*Rate; WF.nBlockAlign = BytesFmt(Fmt); WF.wBitsPerSample = BitsFmt(Fmt); WF.cbSize = sizeof(WF); int R = waveOutOpen(&WO,0,&WF,(UINT)&waveOutCallBack,(UINT)this,CALLBACK_FUNCTION); assert(R==0); int BufSize = BytesFmt(Fmt)*Size; Buf = new char [2*BufSize]; for (int i = 0; i < BufSize; i++) { Buf[i] = random(16000); } for (int i = BufSize; i < 2*BufSize; i++) { Buf[i] = random(100); } for (int i = 0; i < 2; i++) { ZeroMemory(&WH[i],sizeof(WAVEHDR)); WH[i].lpData = Buf + i*BufSize; WH[i].dwBufferLength = BufSize; R = waveOutPrepareHeader(WO,&WH[i],sizeof(WAVEHDR)); assert(R==0); } } CBuffer::~CBuffer() { waveOutPause(WO); for (int i = 0; i<2; i++) { waveOutUnprepareHeader(WO,&WH[i],sizeof(WAVEHDR)); } waveOutClose(WO); } void CBuffer::Play(int n) { int R = waveOutWrite(WO, &WH[n], sizeof(WAVEHDR)); //if (R!=0) assert((R==0)|(R==33)); } void CBuffer::Pause() { int R = waveOutPause(WO); assert(R==0); } void CBuffer::Restart() { int R = waveOutRestart(WO); assert(R==0); } void CBuffer::Reset() { int R = waveOutReset(WO); assert(R==0); } void CBuffer::SetVol(int aVol) { unsigned int V = aVol*256*256+aVol; int R = waveOutSetVolume(WO,V); assert(R==0); } int CBuffer::GetBufNum(void *P) { if (P==&WH[0]) return 0; if (P==&WH[1]) return 1; assert(false); return -1; } void *CBuffer::GetBufPtr(int N) { return WH[N].lpData; //return Buf+N*BufSize; } CPlayTh::CPlayTh(CPlayer *aPlayer):TThread(true) { Player = aPlayer; Priority = tpTimeCritical; SignalDone = CreateEvent(NULL,true,false,NULL); Resume(); } void __fastcall CPlayTh::Execute() { do{ WaitForSingleObject(SignalDone,INFINITE); ResetEvent(SignalDone); if (!Terminated) Player->LoadTh(); }while (!Terminated); } void CPlayTh::Done() { SetEvent(SignalDone); } void CPlayer::LoadNextFrame(int nBuf) { Wav->Read( Buf->GetBufPtr(nBuf) ); } void CPlayer::DoneBuf(int n) { //if (n==0) {n = 1;} else n = 0; nBuf = n; bool DoneFile = Wav->GetPos() >= Wav->GetBufCount(); if (!DoneFile) Th->Done(); if (Wnd!=0) { PostMessage(Wnd,WM_USER,PM_DONE_BUF,n); if (DoneFile) PostMessage(Wnd,WM_USER,PM_DONE_FILE,0); } } void __fastcall CPlayer::LoadTh() { EnterCriticalSection(&CS); int Temp = nBuf; LoadNextFrame(Temp); if (Played) Buf->Play(Temp); LeaveCriticalSection(&CS); } CPlayer::CPlayer(CWAVE *aWav, HWND W) { Wav = aWav; Buf = new CBuffer(Wav->GetFmt(), Wav->GetSize(), Wav->GetRate()); Buf->pPlayer = this; InitializeCriticalSection(&CS); SetPos(0); Th = new CPlayTh(this); Paused = false; Played = false; Wnd = W; } CPlayer::~CPlayer() { Th->Terminate(); Th->Done(); Th->WaitFor(); delete Th; delete Buf; } void CPlayer::SetPos(int nPos) { bool Pl = (Played)&&(!Paused); Played = false; Paused = false; EnterCriticalSection(&CS); Buf->Reset(); Wav->SetPos(nPos); LoadNextFrame(0); LoadNextFrame(1); if (Pl) Play(); LeaveCriticalSection(&CS); } void CPlayer::SetVol(int aVol) { Buf->SetVol(aVol); } void CPlayer::Play() { if (!Paused) { Buf->Play(0); Buf->Play(1); }else Buf->Restart(); Paused = false; Played = true; } void CPlayer::Pause() { Buf->Pause(); Paused = true; } Ошибка 33 возникает при попытке сменить позицию воспроизведения у плейера, когда он воспроизодит файл. |
Сообщ.
#13
,
|
|
|
В общем, что я выяснил. 33 вылезает, если попытаться впихнуть через waveoutwrite в очередь заголовок, который уже и так в очереди. Кроме того, если попытаться выполнить unprepare такого заголовка. Как бы 33 так и говорит: The data block pointed to by the pwh parameter is still in the queue("оно уже/ещё играется, чё ты хочешь?"). Так что это всё-таки ошибка(в программе), а где именно, не скажу, так как в сишной программе не ориентируюсь.
|
Сообщ.
#14
,
|
|
|
Тогда такой вопрос. Если у устройства один буфер воспроизводится, а второй находится в очереди на воспроизвидения, при сбросе устройства (waveOutReset(WO)) оба буфера будут удалены из очереди?
Добавлено В спавке пишут что все буфера из очереди высвобождаются и помечаются как выполненые. а вот генерируется ли сообщение DONE не написано. Я исходил из того что оно при Reset не генерируется. |
Сообщ.
#15
,
|
|
|
Да, все будут удалены. И да, на каждый будет сгенерировано DONE.
И ещё в другой теме я писал, по поводу waveinreset, на всякий пожарный: Цитата Кстати, столкнулся с непонятным явлением. Waveinreset выбросит из очереди все буферы и процесс записи будет остановлен. При этом поле dwBytesRecorded будет содержать фактическое количество записанной информации до того момента когда запись была прервана, или ноль, для тех буферов, которые ожидали своей очереди. Так вот. Если в консольном приложении вызвать Waveinreset, то в кэлбэке при попытке расфиксировать такой буфер(wavinunprepareheader) возникает исключение. В то же время, если приложение не консольное, ничего подобного не происходит. В чем причина, пока не понял, возможно, я где-то ошибся или что-то недопонял. |
Сообщ.
#16
,
|
|
|
Цитата Prince @ И да, на каждый будет сгенерировано DONE. Ну похоже именно в этом дело. На скорую руку переделал код. Ошибка перестала появлятся при перемещении движка Только теперь воспроизведени не запускается программно, а исключительно с толкача (надо подвигать движок позиции мышкой) Ну нафиг, лучше не буду ничего трогать |