waveout_win32.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:26k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*****************************************************************************
  2.  *
  3.  * This program is free software ; you can redistribute it and/or modify
  4.  * it under the terms of the GNU General Public License as published by
  5.  * the Free Software Foundation; either version 2 of the License, or
  6.  * (at your option) any later version.
  7.  *
  8.  * This program is distributed in the hope that it will be useful,
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11.  * GNU General Public License for more details.
  12.  *
  13.  * You should have received a copy of the GNU General Public License
  14.  * along with this program; if not, write to the Free Software
  15.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  16.  *
  17.  * $Id: waveout_win32.c 543 2006-01-07 22:06:24Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "../common.h"
  24. #include <math.h>
  25. #if defined(TARGET_WIN32) || defined(TARGET_WINCE)
  26. #define BUFFER_MUSIC 1*TICKSPERSEC
  27. #define BUFFER_VIDEO 2*TICKSPERSEC
  28. #ifndef STRICT
  29. #define STRICT
  30. #endif
  31. #include <windows.h>
  32. #define BENCH_SIZE 32
  33. struct waveout;
  34. typedef struct wavebuffer
  35. {
  36. WAVEHDR Head;
  37. planes Planes;
  38. struct wavebuffer* Next; //next in chain
  39. struct wavebuffer* GlobalNext;
  40. tick_t RefTime;
  41. tick_t EstRefTime;
  42. int Bytes;
  43. block Block;
  44. } wavebuffer;
  45. typedef struct waveout
  46. {
  47. node Node;
  48. node Timer;
  49. pin Pin;
  50. packetformat Input;
  51. packetformat Output;
  52. packetprocess Process;
  53. wavebuffer* Buffers; // global chain
  54. wavebuffer* FreeFirst;
  55. wavebuffer* FreeLast;
  56. int BufferLength; // one buffer length (waveout format)
  57. tick_t BufferScaledTime; // scaled time of one waveout buffer (BufferLength)
  58. int BufferScaledAdjust; // waveout bytes to scaled time convert (12bit fixed point)
  59. int Total; // source format
  60. int Dropped; // dropped packets
  61. int Bytes; // output format
  62. int FillPos;
  63. int Skip;
  64. wavebuffer* FillFirst;
  65. wavebuffer* FillLast;
  66. wavebuffer** Pausing;
  67. tick_t FillLastTime;
  68. HWAVEOUT Handle;
  69. CRITICAL_SECTION Section;
  70. void* PCM;
  71. int PCMSpeed;
  72. int BufferLimit;
  73. int BufferLimitFull;
  74. tick_t Tick;
  75. int TimeRef;
  76. LONG Waiting; // number of waiting buffers in WaveOut
  77. LONG Used; // number of used buffers (waiting or in fill chain)
  78. bool_t Play;
  79. fraction Speed;
  80. fraction SpeedTime;
  81. int AdjustedRate;
  82. bool_t Dither;
  83. bool_t BufferMode;
  84. int Stereo;
  85. int Quality;
  86. bool_t ForcePriority;
  87. bool_t SoftwareVolume;
  88. bool_t MonoVol;
  89. bool_t Mute; 
  90. int PreAmp;
  91. int VolumeDev; // backup value when mute is turned on
  92. int VolumeSoft;
  93. int VolumeSoftLog;
  94. int VolumeRamp;
  95. WAVEFORMATEX Format;
  96. int BenchWait[BENCH_SIZE];
  97. int BenchSum[BENCH_SIZE];
  98. int BenchCurrSum;
  99. int BenchAvg;
  100. int BenchAdj;
  101. size_t BenchAvgLimit;
  102. int BenchSpeedAvg;
  103. int BenchWaitPos;
  104. } waveout;
  105. #define WAVEOUT(p) ((waveout*)((char*)(p)-OFS(waveout,Timer)))
  106. static void Pause(waveout* p);
  107. static void Write(waveout* p, tick_t CurrTime);
  108. static int SetVolumeSoft(waveout* p,int v,bool_t m)
  109. {
  110. int OldVolumeSoftLog = p->VolumeSoftLog;
  111. bool_t OldSkip = p->Mute || p->VolumeSoft==0;
  112. p->VolumeSoft = v;
  113. p->Mute = m;
  114. if (p->SoftwareVolume || p->PreAmp)
  115. {
  116. if (p->SoftwareVolume && p->Handle && (p->Mute || p->VolumeSoft==0)!=OldSkip)
  117. {
  118. if (!OldSkip)
  119. Pause(p);
  120. else 
  121. if (p->Play)
  122. {
  123. // adjust tick so packets without RefTime won't mess up timing
  124. EnterCriticalSection(&p->Section);
  125. p->Tick += Scale(GetTimeTick()-p->TimeRef,p->SpeedTime.Num,p->SpeedTime.Den);
  126. p->TimeRef = GetTimeTick();
  127. LeaveCriticalSection(&p->Section);
  128. }
  129. }
  130. v += p->PreAmp;
  131. if (v<-40) v=-40;
  132. p->VolumeSoftLog = (int)(pow(10,(50+v)/62.3));
  133. if (p->VolumeSoftLog < 3)
  134. p->VolumeSoftLog = 3;
  135. }
  136. else
  137. p->VolumeSoftLog = 256;
  138. if (p->Handle)
  139. {
  140. int Adjust = ScaleRound(p->VolumeSoftLog,256,OldVolumeSoftLog);
  141. if (Adjust != 256)
  142. {
  143. wavebuffer* List;
  144. EnterCriticalSection(&p->Section);
  145. for (List=p->Buffers;List;List=List->GlobalNext)
  146. VolumeMul(Adjust,(void*)List->Block.Ptr,p->BufferLength,&p->Output.Format.Audio);
  147. LeaveCriticalSection(&p->Section);
  148. }
  149. }
  150. return ERR_NONE;
  151. }
  152. static int GetVolume(waveout* p)
  153. {
  154. if (!p->SoftwareVolume)
  155. {
  156. DWORD Value;
  157. if (waveOutGetVolume(NULL,&Value) == MMSYSERR_NOERROR)
  158. {
  159. if (p->MonoVol)
  160. {
  161. Value &= 0xFFFF;
  162. Value |= Value << 16;
  163. }
  164. if (Value)
  165. p->Mute = 0;
  166. if (!p->Mute)
  167. p->VolumeDev = ((LOWORD(Value)+HIWORD(Value)+600)*100) / (0xFFFF*2);
  168. }
  169. return p->VolumeDev;
  170. }
  171. return p->VolumeSoft;
  172. }
  173. static tick_t Time(waveout* p)
  174. {
  175. if (p->Speed.Num==0)
  176. return TIME_BENCH;
  177. if (p->Play)
  178. {
  179. tick_t t;
  180. EnterCriticalSection(&p->Section);
  181. t = p->Tick + Scale(GetTimeTick()-p->TimeRef,p->SpeedTime.Num,p->SpeedTime.Den);
  182. LeaveCriticalSection(&p->Section);
  183. return t;
  184. }
  185. return p->Tick;
  186. }
  187. static int TimerGet(void* pt, int No, void* Data, int Size)
  188. {
  189. waveout* p = WAVEOUT(pt);
  190. int Result = ERR_INVALID_PARAM;
  191. switch (No)
  192. {
  193. case TIMER_PLAY: GETVALUE(p->Play,bool_t); break;
  194. case TIMER_SPEED: GETVALUE(p->Speed,fraction); break;
  195. case TIMER_TIME: GETVALUE(Time(p),tick_t); break;
  196. }
  197. return Result;
  198. }
  199. static int Get(waveout* p, int No, void* Data, int Size)
  200. {
  201. int Result = ERR_INVALID_PARAM;
  202. switch (No)
  203. {
  204. case OUT_INPUT: GETVALUE(p->Pin,pin); break;
  205. case OUT_INPUT|PIN_FORMAT: GETVALUE(p->Input,packetformat); break;
  206. case OUT_INPUT|PIN_PROCESS: GETVALUE(p->Process,packetprocess); break;
  207. case OUT_OUTPUT|PIN_FORMAT: GETVALUE(p->Output,packetformat); break;
  208. case OUT_TOTAL:GETVALUE(p->Total,int); break;
  209. case OUT_DROPPED:GETVALUE(p->Dropped,int); break;
  210. case AOUT_VOLUME: GETVALUE(GetVolume(p),int); break;
  211. case AOUT_MUTE: GETVALUE(p->Mute,bool_t); break;
  212. case AOUT_PREAMP: GETVALUE(p->PreAmp,int); break;
  213. case AOUT_STEREO: GETVALUE(p->Stereo,int); break; 
  214. case AOUT_MODE: GETVALUE(p->BufferMode,bool_t); break;
  215. case AOUT_QUALITY: GETVALUE(p->Quality,int); break;
  216. case AOUT_TIMER: GETVALUE(&p->Timer,node*); break;
  217. }
  218. return Result;
  219. }
  220. static void UpdateBenchAvg(waveout* p)
  221. {
  222. int n;
  223. p->BenchAvg += 4;
  224. p->BenchAdj = (24*16) / p->BenchAvg;
  225. p->BenchSpeedAvg = SPEED_ONE/(p->BenchAvg*BENCH_SIZE);
  226. n = p->Input.Format.Audio.Bits >> 3;
  227. if (!(p->Input.Format.Audio.Flags & PCM_PLANES))
  228. n *= p->Input.Format.Audio.Channels;
  229. n = p->Output.Format.Audio.SampleRate;
  230. if (n>0)
  231. p->BenchAvgLimit = (n * p->BenchAvg) / 160;
  232. else
  233. p->BenchAvgLimit = MAX_INT;
  234. p->BenchCurrSum += 2 * BENCH_SIZE;
  235. for (n=0;n<BENCH_SIZE;++n)
  236. {
  237. p->BenchSum[n] += 2 * BENCH_SIZE;
  238. p->BenchWait[n] += 2;
  239. }
  240. }
  241. static void ReleaseBuffer(waveout* p,wavebuffer* Buffer,bool_t UpdateTick)
  242. {
  243. EnterCriticalSection(&p->Section);
  244. if (UpdateTick)
  245. {
  246. tick_t Old;
  247. int Time = GetTimeTick();
  248. Old = p->Tick + Scale(Time-p->TimeRef,p->SpeedTime.Num,p->SpeedTime.Den);
  249. if (Buffer->RefTime >= 0)
  250. p->Tick = Buffer->RefTime + p->BufferScaledTime;
  251. else
  252. p->Tick += p->BufferScaledTime;
  253. p->TimeRef = Time;
  254. //DEBUG_MSG2(-1,T("WaveOutTime: %d %d"),Old,p->Tick);
  255. // if difference is little then just adjust (because GetTimeTick() is more linear)
  256. if (abs(Old - p->Tick) < TICKSPERSEC/2)
  257. p->Tick = Old + ((p->Tick - Old) >> 2);
  258. }
  259. Buffer->Next = NULL;
  260. if (p->FreeLast)
  261. p->FreeLast->Next = Buffer;
  262. else
  263. p->FreeFirst = Buffer;
  264. p->FreeLast = Buffer;
  265. p->Used--;
  266. LeaveCriticalSection(&p->Section);
  267. }
  268. static void Reset(waveout* p)
  269. {
  270. int n;
  271. // release buffers already sended to device
  272. if (p->Handle)
  273. {
  274. tick_t OldTick = p->Tick;
  275. waveOutReset(p->Handle);
  276. p->Tick = OldTick;
  277. }
  278. if (p->FillLast && p->FillLast->RefTime >= 0)
  279. p->FillLastTime = p->FillLast->RefTime;
  280. // release fill chain
  281. while (p->FillFirst)
  282. {
  283. wavebuffer* Buffer = p->FillFirst;
  284. p->FillFirst = Buffer->Next;
  285. ReleaseBuffer(p,Buffer,0);
  286. }
  287. p->FillLast = NULL;
  288. p->FillPos = p->BufferLength;
  289. p->Skip = 0;
  290. p->Bytes = 0;
  291. p->BufferLimit = p->BufferLimitFull;
  292. p->BenchAvg = 16-4;
  293. UpdateBenchAvg(p);
  294. p->BenchWaitPos = 0;
  295. p->BenchCurrSum = p->BenchAvg * BENCH_SIZE;
  296. for (n=0;n<BENCH_SIZE;++n)
  297. {
  298. p->BenchSum[n] = p->BenchCurrSum;
  299. p->BenchWait[n] = p->BenchAvg;
  300. }
  301. PCMReset(p->PCM); // init dither and subsample position
  302. }
  303. static wavebuffer* GetBuffer(waveout* p)
  304. {
  305. wavebuffer* Buffer;
  306. // try to find a free buffer
  307. EnterCriticalSection(&p->Section);
  308. Buffer = p->FreeFirst;
  309. if (Buffer)
  310. {
  311. p->FreeFirst = Buffer->Next;
  312. if (Buffer == p->FreeLast)
  313. p->FreeLast = NULL;
  314. }
  315. if (!Buffer)
  316. {
  317. block Block;
  318. if (AllocBlock(p->BufferLength,&Block,p->Used>=20,HEAP_DYNAMIC))
  319. {
  320. Buffer = (wavebuffer*)malloc(sizeof(wavebuffer));
  321. if (!Buffer)
  322. FreeBlock(&Block);
  323. }
  324. if (Buffer)
  325. {
  326. Buffer->Block = Block;
  327. Buffer->Planes[0] = (uint8_t*)Block.Ptr;
  328. Buffer->Next = NULL;
  329. memset(&Buffer->Head,0,sizeof(WAVEHDR));
  330. Buffer->Head.lpData = (char*)Buffer->Block.Ptr;
  331. Buffer->Head.dwUser = (DWORD)Buffer;
  332. Buffer->Head.dwBufferLength = p->BufferLength;
  333. Buffer->Head.dwBytesRecorded = p->BufferLength;
  334. if (waveOutPrepareHeader(p->Handle, &Buffer->Head, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
  335. {
  336. FreeBlock(&Buffer->Block);
  337. free(Buffer);
  338. Buffer = NULL;
  339. }
  340. else
  341. {
  342. Buffer->GlobalNext = p->Buffers;
  343. p->Buffers = Buffer;
  344. }
  345. }
  346. else
  347. {
  348. p->BufferLimitFull = p->Used;
  349. if (p->BufferLimit > p->Used)
  350. p->BufferLimit = p->Used;
  351. else
  352. if (p->BufferLimit > 4)
  353. p->BufferLimit--;
  354. }
  355. }
  356. if (Buffer)
  357. {
  358. p->Used++;
  359. Buffer->RefTime = -1;
  360. Buffer->Next =NULL;
  361. }
  362. LeaveCriticalSection(&p->Section);
  363. return Buffer;
  364. }
  365. static void Write(waveout* p, tick_t CurrTime)
  366. {
  367. if (p->Play)
  368. {
  369. while (p->FillFirst != p->FillLast)
  370. {
  371. wavebuffer* Buffer = p->FillFirst;
  372. if (!p->Waiting && CurrTime >= 0 && Buffer->EstRefTime >= 0 && Buffer->EstRefTime > CurrTime + SHOWAHEAD)
  373. break;
  374. p->FillFirst = Buffer->Next;
  375. if (p->SoftwareVolume && (p->Mute || p->VolumeSoft==0))
  376. ReleaseBuffer(p,Buffer,0);
  377. else
  378. {
  379. if (waveOutWrite(p->Handle, &Buffer->Head, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
  380. ReleaseBuffer(p,Buffer,0);
  381. else
  382. InterlockedIncrement(&p->Waiting);
  383. }
  384. }
  385. }
  386. }
  387. static int Send(waveout* p, const constplanes Planes, int Length, tick_t RefTime, tick_t CurrTime, int Speed)
  388. {
  389. wavebuffer* Buffer;
  390. int DstLength;
  391. int SrcLength;
  392. planes DstPlanes;
  393. constplanes SrcPlanes;
  394. p->Total += Length;
  395. SrcPlanes[0] = Planes[0];
  396. SrcPlanes[1] = Planes[1];
  397. if (p->Skip > 0)
  398. {
  399. SrcLength = min(p->Skip,Length);
  400. SrcPlanes[0] = (uint8_t*)SrcPlanes[0] + SrcLength;
  401. SrcPlanes[1] = (uint8_t*)SrcPlanes[1] + SrcLength;
  402. Length -= SrcLength;
  403. p->Skip -= SrcLength;
  404. }
  405. while (Length > 0)
  406. {
  407. if (p->FillPos >= p->BufferLength)
  408. {
  409. // allocate new buffer
  410. Buffer = GetBuffer(p);
  411. if (!Buffer)
  412. break;
  413. if (p->FillLast)
  414. {
  415. wavebuffer* Last = p->FillLast;
  416. if (Last->RefTime>=0)
  417. p->FillLastTime = Last->EstRefTime = Last->RefTime;
  418. else
  419. {
  420. if (p->FillLastTime>=0)
  421. p->FillLastTime += p->BufferScaledTime;
  422. Last->EstRefTime = p->FillLastTime;
  423. }
  424. Last->Next = Buffer;
  425. }
  426. else
  427. p->FillFirst = Buffer;
  428. p->FillLast = Buffer;
  429. p->FillPos = 0;
  430. Buffer->Bytes = p->Bytes;
  431. }
  432. else
  433. Buffer = p->FillLast;
  434. if (RefTime >= 0)
  435. {
  436. Buffer->RefTime = RefTime - ((p->FillPos * p->BufferScaledAdjust) >> 12);
  437. if (Buffer->RefTime < 0)
  438. Buffer->RefTime = 0;
  439. RefTime = TIME_UNKNOWN;
  440. }
  441. SrcLength = Length;
  442. DstLength = p->BufferLength - p->FillPos;
  443. DstPlanes[0] = (uint8_t*)Buffer->Block.Ptr + p->FillPos;
  444. PCMConvert(p->PCM,DstPlanes,SrcPlanes,&DstLength,&SrcLength,Speed,p->VolumeSoftLog);
  445. if (p->VolumeRamp < RAMPLIMIT)
  446. p->VolumeRamp = VolumeRamp(p->VolumeRamp,DstPlanes[0],DstLength,&p->Output.Format.Audio);
  447. p->Bytes += DstLength;
  448. p->FillPos += DstLength;
  449. SrcPlanes[0] = (uint8_t*)SrcPlanes[0] + SrcLength;
  450. SrcPlanes[1] = (uint8_t*)SrcPlanes[1] + SrcLength;
  451. Length -= SrcLength;
  452. if (!SrcLength)
  453. break;
  454. }
  455. if (Length && p->Input.Format.Audio.BlockAlign>0)
  456. p->Skip = p->Input.Format.Audio.BlockAlign - Length % p->Input.Format.Audio.BlockAlign;
  457. Write(p,CurrTime);
  458. return ERR_NONE;
  459. }
  460. static void CALLBACK WaveProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, 
  461.                                DWORD dwParam1, DWORD dwParam2)
  462. {
  463.     if (uMsg == WOM_DONE)
  464.     {
  465. wavebuffer* Buffer = (wavebuffer*)(((WAVEHDR*)dwParam1)->dwUser);
  466. waveout* p = (waveout*)dwInstance;
  467. if (p->ForcePriority)
  468. {
  469. void* Thread = GetCurrentThread();
  470. if (GetThreadPriority(Thread)!=THREAD_PRIORITY_HIGHEST)
  471. SetThreadPriority(Thread,THREAD_PRIORITY_HIGHEST);
  472. }
  473. if (p->Pausing)
  474. {
  475. // add buffer to fill chain
  476. Buffer->Next = *p->Pausing;
  477. *p->Pausing = Buffer;
  478. p->Pausing = &Buffer->Next;
  479. }
  480. else
  481. ReleaseBuffer(p,Buffer,1);
  482. InterlockedDecrement(&p->Waiting);
  483.     }
  484. }
  485. static int UpdatePCM(waveout* p,const audio* InputFormat)
  486. {
  487. p->SpeedTime = p->Speed;
  488. p->SpeedTime.Num *= TICKSPERSEC;
  489. p->SpeedTime.Den *= GetTimeFreq();
  490. p->BufferScaledTime = Scale(TICKSPERSEC,p->Speed.Num*p->BufferLength,p->Speed.Den*p->Format.nAvgBytesPerSec);
  491. if (p->BufferLength)
  492. p->BufferScaledAdjust = (p->BufferScaledTime*4096) / p->BufferLength;
  493. else
  494. p->BufferScaledAdjust = 0;
  495. if (!p->Speed.Num)
  496. p->PCMSpeed = SPEED_ONE;
  497. else
  498. p->PCMSpeed = Scale(SPEED_ONE,p->Speed.Num,p->Speed.Den);
  499. p->AdjustedRate = Scale(p->Output.Format.Audio.SampleRate,p->Speed.Den,p->Speed.Num);
  500. PCMRelease(p->PCM);
  501. p->PCM = PCMCreate(&p->Output.Format.Audio,InputFormat,p->Dither,p->SoftwareVolume || p->PreAmp);
  502. return ERR_NONE;
  503. }
  504. static int UpdateBufferTime(waveout* p)
  505. {
  506. p->BufferLimit = Scale(p->BufferMode?BUFFER_VIDEO:BUFFER_MUSIC,p->Format.nAvgBytesPerSec,p->BufferLength*TICKSPERSEC);
  507. p->BufferLimitFull = p->BufferLimit;
  508. return ERR_NONE;
  509. }
  510. static int Process(waveout* p,const packet* Packet,const flowstate* State)
  511. {
  512. if (!Packet)
  513. {
  514. if (State->DropLevel)
  515. ++p->Dropped;
  516. else
  517. Write(p,State->CurrTime);
  518. return (p->Waiting<=0 || p->Speed.Num==0) ? ERR_NONE : ERR_BUFFER_FULL;
  519. }
  520. if (p->Speed.Num==0) // benchmark mode (auto adjust speed)
  521. {
  522. int Pos = p->BenchWaitPos;
  523. int OldSum;
  524. int Speed;
  525. if (p->Play)
  526. {
  527. while (Packet->Length > p->BenchAvgLimit)
  528. UpdateBenchAvg(p);
  529. p->BenchCurrSum -= p->BenchWait[Pos];
  530. p->BenchWait[Pos] = (p->Waiting * p->BufferLength) >> 12;
  531. p->BenchCurrSum += p->BenchWait[Pos];
  532. OldSum = p->BenchSum[Pos];
  533. p->BenchSum[Pos] = p->BenchCurrSum;
  534. if (++Pos == BENCH_SIZE)
  535. Pos = 0;
  536. p->BenchWaitPos = Pos;
  537. if (p->BenchCurrSum < 2*BENCH_SIZE*p->BenchAvg)
  538. Speed = (p->BenchCurrSum+1) * p->BenchSpeedAvg;
  539. else
  540. Speed = 2*SPEED_ONE+(p->BenchCurrSum-2*BENCH_SIZE*p->BenchAvg+1) * 4*p->BenchSpeedAvg;
  541. Speed -= p->BenchAdj*(p->BenchCurrSum - OldSum);
  542. if (p->Waiting < 3)
  543. Speed -= SPEED_ONE/5;
  544. }
  545. else
  546. Speed = SPEED_ONE;
  547. //DEBUG_MSG3(-1,T("Audio speed:%d length:%d (wait:%d)"),Speed,Packet->Length,p->Waiting);
  548. return Send(p,Packet->Data,Packet->Length,Packet->RefTime,State->CurrTime,Speed);
  549. }
  550. if (State->DropLevel)
  551. return ERR_NONE;
  552. if (p->Used >= p->BufferLimit)
  553. {
  554. Write(p,State->CurrTime);
  555. return ERR_BUFFER_FULL;
  556. }
  557. DEBUG_MSG3(DEBUG_AUDIO,T("Waveout reftime:%d used:%d waiting:%d"),Packet->RefTime,p->Used,p->Waiting);
  558. return Send(p,Packet->Data,Packet->Length,Packet->RefTime,State->CurrTime,p->PCMSpeed);
  559. }
  560. static bool_t FreeBuffers(waveout* p);
  561. static int UpdateInput(waveout* p)
  562. {
  563. Reset(p);
  564. FreeBuffers(p);
  565. if (p->Handle)
  566. {
  567. waveOutClose(p->Handle);
  568. p->Handle = NULL;
  569. }
  570. p->Total = 0;
  571. p->Dropped = 0;
  572. p->Process = DummyProcess;
  573. if (p->Input.Type == PACKET_AUDIO)
  574. {
  575. MMRESULT MMResult;
  576. int Try;
  577. if (p->Input.Format.Audio.Format != AUDIOFMT_PCM) 
  578. {
  579. PacketFormatClear(&p->Input);
  580. return ERR_INVALID_DATA;
  581. }
  582. if (p->Input.Format.Audio.Channels == 0 ||
  583. p->Input.Format.Audio.SampleRate == 0)
  584. return ERR_NONE; // probably initialized later
  585. p->Output.Type = PACKET_AUDIO;
  586. p->Output.Format.Audio = p->Input.Format.Audio;
  587. p->Output.Format.Audio.Flags = 0;
  588. p->Dither = 0;
  589. if (p->Stereo==STEREO_SWAPPED)
  590. p->Output.Format.Audio.Flags |= PCM_SWAPPEDSTEREO;
  591. else
  592. if (p->Stereo!=STEREO_NORMAL)
  593. {
  594. p->Output.Format.Audio.Channels = 1;
  595. if (p->Stereo==STEREO_LEFT)
  596. p->Output.Format.Audio.Flags |= PCM_ONLY_LEFT;
  597. if (p->Stereo==STEREO_RIGHT)
  598. p->Output.Format.Audio.Flags |= PCM_ONLY_RIGHT;
  599. }
  600. switch (p->Quality)
  601. {
  602. case 0: // low quality for very poor devices
  603. p->Output.Format.Audio.Bits = 8;
  604. p->Output.Format.Audio.FracBits = 7;
  605. p->Output.Format.Audio.Channels = 1;
  606. p->Output.Format.Audio.SampleRate = 22050;
  607. break;
  608. case 1: // no dither and only standard samplerate
  609. p->Output.Format.Audio.Bits = 16;
  610. p->Output.Format.Audio.FracBits = 15;
  611. if (p->Output.Format.Audio.SampleRate >= 44100)
  612. p->Output.Format.Audio.SampleRate = 44100;
  613. else
  614. p->Output.Format.Audio.SampleRate = 22050;
  615. break;
  616. default:
  617. case 2: // original samplerate 
  618. p->Output.Format.Audio.Bits = 16;
  619. p->Output.Format.Audio.FracBits = 15;
  620. p->Dither = 1;
  621. break;
  622. }
  623. Try = 0;
  624. do
  625. {
  626. if (p->Output.Format.Audio.Bits <= 8)
  627. p->Output.Format.Audio.Flags |= PCM_UNSIGNED;
  628. p->Format.wFormatTag = WAVE_FORMAT_PCM;
  629. p->Format.nChannels = (WORD)p->Output.Format.Audio.Channels;
  630. p->Format.nSamplesPerSec = p->Output.Format.Audio.SampleRate;
  631. p->Format.wBitsPerSample = (WORD)p->Output.Format.Audio.Bits;
  632. p->Format.nBlockAlign = (WORD)((p->Format.nChannels * p->Format.wBitsPerSample) >> 3);
  633. p->Format.nAvgBytesPerSec = p->Format.nSamplesPerSec * p->Format.nBlockAlign;
  634. p->Format.cbSize = 0;
  635. MMResult = waveOutOpen(&p->Handle, WAVE_MAPPER, &p->Format,(DWORD)WaveProc,
  636. (DWORD)p,CALLBACK_FUNCTION);
  637. if (MMResult==WAVERR_BADFORMAT)
  638. {
  639. ++Try;
  640. if (Try==1)
  641. {
  642. if (p->Output.Format.Audio.SampleRate > 35000)
  643. p->Output.Format.Audio.SampleRate = 44100;
  644. else
  645. ++Try;
  646. }
  647. if (Try==2)
  648. {
  649. if (p->Output.Format.Audio.SampleRate != 22050)
  650. p->Output.Format.Audio.SampleRate = 22050;
  651. else
  652. ++Try;
  653. }
  654. if (Try==3)
  655. {
  656. if (p->Output.Format.Audio.Channels > 1)
  657. p->Output.Format.Audio.Channels = 1;
  658. else
  659. ++Try;
  660. }
  661. if (Try==4)
  662. {
  663. if (p->Output.Format.Audio.Bits != 8)
  664. {
  665. p->Output.Format.Audio.Bits = 8;
  666. p->Output.Format.Audio.FracBits = 7;
  667. }
  668. else
  669. ++Try;
  670. }
  671. if (Try==5)
  672. break;
  673. }
  674. }
  675. while (MMResult==WAVERR_BADFORMAT);
  676. if (p->Handle)
  677. {
  678. p->Process = Process;
  679. p->TimeRef = GetTimeTick();
  680. p->BufferLength = 4096;
  681. if (p->Format.nAvgBytesPerSec > 65536)
  682. p->BufferLength *= 2;
  683. if (p->Format.nAvgBytesPerSec > 2*65536)
  684. p->BufferLength *= 2;
  685. UpdateBufferTime(p);
  686. p->FillPos = p->BufferLength;
  687. p->VolumeRamp = 0;
  688. UpdatePCM(p,&p->Input.Format.Audio);
  689. Reset(p);
  690. }
  691. else
  692. {
  693. PacketFormatClear(&p->Input);
  694. ShowError(p->Node.Class,ERR_ID,ERR_DEVICE_ERROR);
  695. return ERR_DEVICE_ERROR;
  696. }
  697. }
  698. else
  699. if (p->Input.Type != PACKET_NONE)
  700. return ERR_INVALID_DATA;
  701. return ERR_NONE;
  702. }
  703. static int Update(waveout* p)
  704. {
  705. wavebuffer *OldFirst;
  706. wavebuffer *OldLast;
  707. audio OldFormat;
  708. wavebuffer* OldBuffers;
  709. wavebuffer* OldFill;
  710. int OldFillPos; 
  711. int OldUsed;
  712. bool_t OldVolume;
  713. int OldPreAmp;
  714. wavebuffer *Buffer,*Next;
  715. EnterCriticalSection(&p->Section);
  716. OldVolume = p->SoftwareVolume;
  717. OldPreAmp = p->PreAmp;
  718. OldUsed = p->Used;
  719. OldFirst = p->FreeFirst;
  720. OldLast = p->FreeLast;
  721. OldFormat = p->Output.Format.Audio;
  722. OldFormat.SampleRate = p->AdjustedRate;
  723. OldFill = p->FillFirst;
  724. OldFillPos = p->FillPos;
  725. p->FillFirst = NULL;
  726. p->FillLast = NULL;
  727. p->FillPos = p->BufferLength;
  728. p->FreeFirst = NULL;
  729. p->FreeLast = NULL;
  730. LeaveCriticalSection(&p->Section);
  731. Reset(p);
  732. OldBuffers = p->FreeFirst;
  733. if (p->FreeLast)
  734. p->FreeLast->Next = OldFill;
  735. else
  736. OldBuffers = OldFill;
  737. if (OldBuffers)
  738. p->FillLastTime = OldBuffers->EstRefTime - p->BufferScaledTime;
  739. p->PreAmp = 0;
  740. p->SoftwareVolume = 0;
  741. p->Used = OldUsed;
  742. p->FreeFirst = OldFirst;
  743. p->FreeLast = OldLast;
  744. // setup temporary format
  745. UpdatePCM(p,&OldFormat);
  746. for (Buffer=OldBuffers;Buffer;Buffer=Next)
  747. {
  748. Next = Buffer->Next;
  749. Send(p,Buffer->Planes,Next ? p->BufferLength:OldFillPos,Buffer->RefTime,-1,p->PCMSpeed);
  750. ReleaseBuffer(p,Buffer,0);
  751. }
  752. p->SoftwareVolume = OldVolume;
  753. p->PreAmp = OldPreAmp;
  754. UpdatePCM(p,&p->Input.Format.Audio);
  755. return ERR_NONE;
  756. }
  757. static bool_t FreeBuffers(waveout* p)
  758. {
  759. wavebuffer** Ptr;
  760. wavebuffer* Buffer;
  761. bool_t Changed = 0;
  762. while (p->FreeFirst)
  763. {
  764. Buffer = p->FreeFirst;
  765. p->FreeFirst = Buffer->Next;
  766. // remove from global chain
  767. Ptr = &p->Buffers;
  768. while (*Ptr && *Ptr != Buffer)
  769. Ptr = &(*Ptr)->GlobalNext;
  770. if (*Ptr == Buffer)
  771. *Ptr = Buffer->Next;
  772. waveOutUnprepareHeader(p->Handle, &Buffer->Head, sizeof(WAVEHDR));
  773. FreeBlock(&Buffer->Block);
  774. free(Buffer);
  775. Changed = 1;
  776. }
  777. p->FreeLast = NULL;
  778. return Changed;
  779. }
  780. static int Hibernate(waveout* p,int Mode)
  781. {
  782. bool_t Changed = 0;
  783. EnterCriticalSection(&p->Section);
  784. Changed = FreeBuffers(p);
  785. LeaveCriticalSection(&p->Section);
  786. return Changed ? ERR_NONE : ERR_OUT_OF_MEMORY;
  787. }
  788. static void Pause(waveout* p)
  789. {
  790. p->Pausing = &p->FillFirst;
  791. waveOutReset(p->Handle);
  792. p->Pausing = NULL;
  793. p->FillLast = p->FillFirst;
  794. if (p->FillLast)
  795. while (p->FillLast->Next) p->FillLast = p->FillLast->Next;
  796. }
  797. static int UpdatePlay(waveout* p)
  798. {
  799. if (p->Play)
  800. {
  801. p->TimeRef = GetTimeTick();
  802. if (p->Handle)
  803. Write(p,p->Tick);
  804. }
  805. else
  806. {
  807. if (!p->Waiting)
  808. p->Tick += Scale(GetTimeTick()-p->TimeRef,p->SpeedTime.Num,p->SpeedTime.Den);
  809. else
  810. if (p->Handle)
  811. Pause(p);
  812. }
  813. return ERR_NONE;
  814. }
  815. static int SetVolumeDev(waveout* p,int v)
  816. {
  817. p->VolumeDev = v;
  818. if (p->Mute)
  819. waveOutSetVolume(NULL,0);
  820. else
  821. waveOutSetVolume(NULL,0x10001 * ((0xFFFF * p->VolumeDev) / 100));
  822. return ERR_NONE;
  823. }
  824. static int TimerSet(void* pt, int No, const void* Data, int Size)
  825. {
  826. waveout* p = WAVEOUT(pt);
  827. int Result = ERR_INVALID_PARAM;
  828. switch (No)
  829. {
  830. case TIMER_PLAY: SETVALUECMP(p->Play,bool_t,UpdatePlay(p),EqBool); break;
  831. case TIMER_SPEED: SETVALUECMP(p->Speed,fraction,Update(p),EqFrac); break;
  832. case TIMER_TIME:
  833. assert(Size == sizeof(tick_t));
  834. EnterCriticalSection(&p->Section);
  835. p->Tick = *(tick_t*)Data;
  836. p->TimeRef = GetTimeTick();
  837. LeaveCriticalSection(&p->Section);
  838. Result = ERR_NONE;
  839. break;
  840. }
  841. return Result;
  842. }
  843. static void UpdateSoftwareVolume(waveout* p)
  844. {
  845. bool_t SoftwareVolume = !QueryAdvanced(ADVANCED_SYSTEMVOLUME);
  846. if (SoftwareVolume != p->SoftwareVolume)
  847. {
  848. p->SoftwareVolume = SoftwareVolume;
  849. SetVolumeSoft(p,p->VolumeSoft,p->Mute);
  850. if (p->Handle)
  851. UpdatePCM(p,&p->Input.Format.Audio);
  852. }
  853. }
  854. static int UpdatePreAmp(waveout* p)
  855. {
  856. SetVolumeSoft(p,p->VolumeSoft,p->Mute);
  857. if (p->Handle)
  858. UpdatePCM(p,&p->Input.Format.Audio);
  859. return ERR_NONE;
  860. }
  861. static int Set(waveout* p, int No, const void* Data, int Size)
  862. {
  863. int Result = ERR_INVALID_PARAM;
  864. switch (No)
  865. {
  866. case OUT_INPUT|PIN_FORMAT: 
  867. if (PacketFormatSimilarAudio(&p->Input,(const packetformat*)Data))
  868. {
  869. PacketFormatCopy(&p->Input,(const packetformat*)Data);
  870. Result = UpdatePCM(p,&p->Input.Format.Audio);
  871. }
  872. else
  873. SETPACKETFORMATCMP(p->Input,packetformat,UpdateInput(p)); 
  874. break;
  875. case OUT_INPUT: SETVALUE(p->Pin,pin,ERR_NONE); break;
  876. case OUT_TOTAL: SETVALUE(p->Total,int,ERR_NONE); break;
  877. case OUT_DROPPED: SETVALUE(p->Dropped,int,ERR_NONE); break;
  878. case AOUT_VOLUME: 
  879. assert(Size==sizeof(int));
  880. UpdateSoftwareVolume(p);
  881. if (p->SoftwareVolume)
  882. Result = SetVolumeSoft(p,*(int*)Data,p->Mute);
  883. else
  884. Result = SetVolumeDev(p,*(int*)Data);
  885. break;
  886. case AOUT_PREAMP: SETVALUECMP(p->PreAmp,int,UpdatePreAmp(p),EqInt); break; 
  887. case AOUT_MUTE:
  888. assert(Size==sizeof(bool_t));
  889. UpdateSoftwareVolume(p);
  890. if (p->SoftwareVolume)
  891. Result = SetVolumeSoft(p,p->VolumeSoft,*(bool_t*)Data);
  892. else
  893. {
  894. if (!p->Mute) GetVolume(p); // save old volume to p->VolumeDev
  895. p->Mute = *(bool_t*)Data;
  896. Result = SetVolumeDev(p,p->VolumeDev);
  897. }
  898. break;
  899. case AOUT_STEREO: SETVALUECMP(p->Stereo,int,UpdateInput(p),EqInt); break; 
  900. case AOUT_QUALITY: SETVALUECMP(p->Quality,int,UpdateInput(p),EqInt); break; 
  901. case AOUT_MODE: SETVALUE(p->BufferMode,bool_t,UpdateBufferTime(p)); break;
  902. case FLOW_FLUSH:
  903. Reset(p);
  904. p->FillLastTime = TIME_UNKNOWN;
  905. p->VolumeRamp = 0;
  906. Result = ERR_NONE;
  907. break;
  908. case NODE_SETTINGSCHANGED:
  909. p->ForcePriority = QueryAdvanced(ADVANCED_WAVEOUTPRIORITY);
  910. break;
  911. case NODE_HIBERNATE:
  912. assert(Size == sizeof(int));
  913. Result = Hibernate(p,*(int*)Data);
  914. break;
  915. }
  916. return Result;
  917. }
  918. static int Create(waveout* p)
  919. {
  920. WAVEOUTCAPS Caps;
  921. if (waveOutGetNumDevs()==0)
  922. return ERR_NOT_SUPPORTED;
  923. waveOutGetDevCaps(WAVE_MAPPER,&Caps,sizeof(Caps));
  924. p->Node.Get = (nodeget)Get;
  925. p->Node.Set = (nodeset)Set;
  926. p->Timer.Class = TIMER_CLASS;
  927. p->Timer.Enum = TimerEnum;
  928. p->Timer.Get = TimerGet;
  929. p->Timer.Set = TimerSet;
  930. p->VolumeDev = 70; //default when device is muted
  931. p->VolumeSoftLog = 256;
  932. p->Quality = 2;
  933. p->Speed.Den = p->Speed.Num = 1;
  934. p->SpeedTime.Num = TICKSPERSEC;
  935. p->SpeedTime.Den = GetTimeFreq();
  936. p->MonoVol = (Caps.dwSupport & WAVECAPS_LRVOLUME) == 0;
  937. InitializeCriticalSection(&p->Section);
  938. return ERR_NONE;
  939. }
  940. static void Delete(waveout* p)
  941. {
  942. PacketFormatClear(&p->Input);
  943. PCMRelease(p->PCM);
  944. DeleteCriticalSection(&p->Section);
  945. }
  946. static const nodedef WaveOut =
  947. {
  948. sizeof(waveout)|CF_GLOBAL,
  949. WAVEOUT_ID,
  950. AOUT_CLASS,
  951. PRI_DEFAULT,
  952. (nodecreate)Create,
  953. (nodedelete)Delete,
  954. };
  955. void WaveOut_Init()
  956. {
  957. NodeRegisterClass(&WaveOut);
  958. }
  959. void WaveOut_Done()
  960. {
  961. NodeUnRegisterClass(WAVEOUT_ID);
  962. }
  963. #endif