pcm_decode.c 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468
  1. /****************************************************************************
  2. * audio/pcm_decode.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <nuttx/config.h>
  24. #include <sys/types.h>
  25. #include <inttypes.h>
  26. #include <stdint.h>
  27. #include <stdbool.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <assert.h>
  31. #include <errno.h>
  32. #include <debug.h>
  33. #include <nuttx/kmalloc.h>
  34. #include <nuttx/audio/audio.h>
  35. #include <nuttx/audio/pcm.h>
  36. #if defined(CONFIG_AUDIO) && defined(CONFIG_AUDIO_FORMAT_PCM)
  37. /****************************************************************************
  38. * Pre-processor Definitions
  39. ****************************************************************************/
  40. /* Configuration ************************************************************/
  41. #define CONFIG_PCM_DEBUG 1 /* For now */
  42. /* Often defined and re-defined macros */
  43. #ifndef MIN
  44. # define MIN(a,b) (((a) < (b)) ? (a) : (b))
  45. #endif
  46. #ifndef MAX
  47. # define MAX(a,b) (((a) > (b)) ? (a) : (b))
  48. #endif
  49. /****************************************************************************
  50. * Private Types
  51. ****************************************************************************/
  52. /* This structure describes the internal state of the PCM decoder */
  53. struct pcm_decode_s
  54. {
  55. /* This is is our our appearance to the outside world. This *MUST* be the
  56. * first element of the structure so that we can freely cast between types
  57. * struct audio_lowerhalf and struct pcm_decode_s.
  58. */
  59. struct audio_lowerhalf_s export;
  60. /* These are our operations that intervene between the player application
  61. * and the lower level driver. Unlike the ops in the struct
  62. * audio_lowerhalf_s, these are writeable because we need to customize a
  63. * few of the methods based upon what is supported by the lower level
  64. * driver.
  65. */
  66. struct audio_ops_s ops;
  67. /* This is the contained, low-level DAC-type device and will receive the
  68. * decoded PCM audio data.
  69. */
  70. FAR struct audio_lowerhalf_s *lower;
  71. /* Session returned from the lower level driver */
  72. #ifdef CONFIG_AUDIO_MULTI_SESSION
  73. FAR void *session;
  74. #endif
  75. /* These are values extracted from WAV file header */
  76. uint32_t samprate; /* 8000, 44100, ... */
  77. uint32_t byterate; /* samprate * nchannels * bpsamp / 8 */
  78. uint8_t align; /* nchannels * bpsamp / 8 */
  79. uint8_t bpsamp; /* Bits per sample: 8 bits = 8, 16 bits = 16 */
  80. uint8_t nchannels; /* Mono=1, Stereo=2 */
  81. bool streaming; /* Streaming PCM data chunk */
  82. #ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
  83. /* Fast forward support */
  84. uint8_t subsample; /* Fast forward rate: See AUDIO_SUBSAMPLE_* defns */
  85. uint8_t skip; /* Number of sample bytes to be skipped */
  86. uint8_t npartial; /* Size of the partially copied sample */
  87. #endif
  88. };
  89. /****************************************************************************
  90. * Private Function Prototypes
  91. ****************************************************************************/
  92. /* Helper functions *********************************************************/
  93. #ifdef CONFIG_PCM_DEBUG
  94. static void pcm_dump(FAR const struct wav_header_s *wav);
  95. #else
  96. # define pcm_dump(w)
  97. #endif
  98. #ifndef CONFIG_AUDIO_FORMAT_RAW
  99. static inline bool pcm_validwav(FAR const struct wav_header_s *wav);
  100. static ssize_t pcm_parsewav(FAR struct pcm_decode_s *priv, uint8_t *data,
  101. apb_samp_t len);
  102. #endif
  103. #ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
  104. static void pcm_subsample_configure(FAR struct pcm_decode_s *priv,
  105. uint8_t subsample);
  106. static void pcm_subsample(FAR struct pcm_decode_s *priv,
  107. FAR struct ap_buffer_s *apb);
  108. #endif
  109. /* struct audio_lowerhalf_s methods *****************************************/
  110. static int pcm_getcaps(FAR struct audio_lowerhalf_s *dev, int type,
  111. FAR struct audio_caps_s *caps);
  112. #ifdef CONFIG_AUDIO_MULTI_SESSION
  113. static int pcm_configure(FAR struct audio_lowerhalf_s *dev,
  114. FAR void *session, FAR const struct audio_caps_s *caps);
  115. #else
  116. static int pcm_configure(FAR struct audio_lowerhalf_s *dev,
  117. FAR const struct audio_caps_s *caps);
  118. #endif
  119. static int pcm_shutdown(FAR struct audio_lowerhalf_s *dev);
  120. #ifdef CONFIG_AUDIO_MULTI_SESSION
  121. static int pcm_start(FAR struct audio_lowerhalf_s *dev, FAR void *session);
  122. #else
  123. static int pcm_start(FAR struct audio_lowerhalf_s *dev);
  124. #endif
  125. #ifndef CONFIG_AUDIO_EXCLUDE_STOP
  126. #ifdef CONFIG_AUDIO_MULTI_SESSION
  127. static int pcm_stop(FAR struct audio_lowerhalf_s *dev, FAR void *session);
  128. #else
  129. static int pcm_stop(FAR struct audio_lowerhalf_s *dev);
  130. #endif
  131. #endif
  132. #ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
  133. #ifdef CONFIG_AUDIO_MULTI_SESSION
  134. static int pcm_pause(FAR struct audio_lowerhalf_s *dev, FAR void *session);
  135. #else
  136. static int pcm_pause(FAR struct audio_lowerhalf_s *dev);
  137. #endif
  138. #ifdef CONFIG_AUDIO_MULTI_SESSION
  139. static int pcm_resume(FAR struct audio_lowerhalf_s *dev, FAR void *session);
  140. #else
  141. static int pcm_resume(FAR struct audio_lowerhalf_s *dev);
  142. #endif
  143. #endif
  144. static int pcm_allocbuffer(FAR struct audio_lowerhalf_s *dev,
  145. FAR struct audio_buf_desc_s *apb);
  146. static int pcm_freebuffer(FAR struct audio_lowerhalf_s *dev,
  147. FAR struct audio_buf_desc_s *apb);
  148. static int pcm_enqueuebuffer(FAR struct audio_lowerhalf_s *dev,
  149. FAR struct ap_buffer_s *apb);
  150. static int pcm_cancelbuffer(FAR struct audio_lowerhalf_s *dev,
  151. FAR struct ap_buffer_s *apb);
  152. static int pcm_ioctl(FAR struct audio_lowerhalf_s *dev,
  153. int cmd, unsigned long arg);
  154. #ifdef CONFIG_AUDIO_MULTI_SESSION
  155. static int pcm_reserve(FAR struct audio_lowerhalf_s *dev,
  156. FAR void **session);
  157. #else
  158. static int pcm_reserve(FAR struct audio_lowerhalf_s *dev);
  159. #endif
  160. #ifdef CONFIG_AUDIO_MULTI_SESSION
  161. static int pcm_release(FAR struct audio_lowerhalf_s *dev,
  162. FAR void *session);
  163. #else
  164. static int pcm_release(FAR struct audio_lowerhalf_s *dev);
  165. #endif
  166. /* Audio callback */
  167. #ifdef CONFIG_AUDIO_MULTI_SESSION
  168. static void pcm_callback(FAR void *arg, uint16_t reason,
  169. FAR struct ap_buffer_s *apb, uint16_t status,
  170. FAR void *session);
  171. #else
  172. static void pcm_callback(FAR void *arg, uint16_t reason,
  173. FAR struct ap_buffer_s *apb, uint16_t status);
  174. #endif
  175. /****************************************************************************
  176. * Private Data
  177. ****************************************************************************/
  178. /****************************************************************************
  179. * Public Data
  180. ****************************************************************************/
  181. /****************************************************************************
  182. * Private Functions
  183. ****************************************************************************/
  184. /****************************************************************************
  185. * Name: pcm_dump
  186. *
  187. * Description:
  188. * Dump a WAV file header.
  189. *
  190. ****************************************************************************/
  191. #ifdef CONFIG_PCM_DEBUG
  192. static void pcm_dump(FAR const struct wav_header_s *wav)
  193. {
  194. _info("Wave file header\n");
  195. _info(" Header Chunk:\n");
  196. _info(" Chunk ID: 0x%08" PRIx32 "\n", wav->hdr.chunkid);
  197. _info(" Chunk Size: %" PRIu32 "\n", wav->hdr.chunklen);
  198. _info(" Format: 0x%08" PRIx32 "\n", wav->hdr.format);
  199. _info(" Format Chunk:\n");
  200. _info(" Chunk ID: 0x%08" PRIx32 "\n", wav->fmt.chunkid);
  201. _info(" Chunk Size: %" PRIu32 "\n", wav->fmt.chunklen);
  202. _info(" Audio Format: 0x%04x\n", wav->fmt.format);
  203. _info(" Num. Channels: %d\n", wav->fmt.nchannels);
  204. _info(" Sample Rate: %" PRIu32 "\n", wav->fmt.samprate);
  205. _info(" Byte Rate: %" PRIu32 "\n", wav->fmt.byterate);
  206. _info(" Block Align: %d\n", wav->fmt.align);
  207. _info(" Bits Per Sample: %d\n", wav->fmt.bpsamp);
  208. _info(" Data Chunk:\n");
  209. _info(" Chunk ID: 0x%08" PRIx32 "\n", wav->data.chunkid);
  210. _info(" Chunk Size: %" PRIu32 "\n", wav->data.chunklen);
  211. }
  212. #endif
  213. /****************************************************************************
  214. * Name: pcm_leuint16
  215. *
  216. * Description:
  217. * Get a 16-bit value stored in little endian order. Unaligned address is
  218. * acceptable.
  219. *
  220. ****************************************************************************/
  221. static uint16_t pcm_leuint16(FAR const uint16_t *ptr)
  222. {
  223. FAR const uint8_t *p = (FAR const uint8_t *)ptr;
  224. return ((p[0] << 0) |
  225. (p[1] << 8));
  226. }
  227. /****************************************************************************
  228. * Name: pcm_leuint32
  229. *
  230. * Description:
  231. * Get a 32-bit value stored in little endian order. Unaligned address is
  232. * acceptable.
  233. *
  234. ****************************************************************************/
  235. static uint32_t pcm_leuint32(FAR const uint32_t *ptr)
  236. {
  237. FAR const uint8_t *p = (FAR const uint8_t *)ptr;
  238. return ((p[0] << 0) |
  239. (p[1] << 8) |
  240. (p[2] << 16) |
  241. (p[3] << 24));
  242. }
  243. /****************************************************************************
  244. * Name: pcm_validwav
  245. *
  246. * Description:
  247. * Return true if this is a valid WAV file header
  248. *
  249. ****************************************************************************/
  250. #ifndef CONFIG_AUDIO_FORMAT_RAW
  251. static inline bool pcm_validwav(FAR const struct wav_header_s *wav)
  252. {
  253. return (wav->hdr.chunkid == WAV_HDR_CHUNKID &&
  254. wav->hdr.format == WAV_HDR_FORMAT &&
  255. wav->fmt.chunkid == WAV_FMT_CHUNKID &&
  256. wav->fmt.chunklen == WAV_FMT_CHUNKLEN &&
  257. wav->fmt.format == WAV_FMT_FORMAT &&
  258. wav->fmt.nchannels < 256 &&
  259. wav->fmt.align < 256 &&
  260. wav->fmt.bpsamp < 256);
  261. }
  262. /****************************************************************************
  263. * Name: pcm_parsewav
  264. *
  265. * Description:
  266. * Parse and verify the WAV file header. A WAV file is a particular
  267. * packaging of an audio file; on PCM encoded WAV files are accepted by
  268. * this driver.
  269. *
  270. ****************************************************************************/
  271. static ssize_t pcm_parsewav(FAR struct pcm_decode_s *priv, uint8_t *data,
  272. apb_samp_t len)
  273. {
  274. FAR const struct wav_header_s *wav = (FAR const struct wav_header_s *)data;
  275. FAR const struct wav_datachunk_s *dchunk;
  276. struct wav_header_s localwav;
  277. size_t ret = sizeof(struct wav_header_s);
  278. if (len < sizeof(struct wav_header_s))
  279. {
  280. return -EINVAL;
  281. }
  282. /* Transfer the purported WAV file header into our stack storage,
  283. * correcting for endian issues as needed.
  284. */
  285. localwav.hdr.chunkid = pcm_leuint32(&wav->hdr.chunkid);
  286. localwav.hdr.chunklen = pcm_leuint32(&wav->hdr.chunklen);
  287. localwav.hdr.format = pcm_leuint32(&wav->hdr.format);
  288. localwav.fmt.chunkid = pcm_leuint32(&wav->fmt.chunkid);
  289. localwav.fmt.chunklen = pcm_leuint32(&wav->fmt.chunklen);
  290. localwav.fmt.format = pcm_leuint16(&wav->fmt.format);
  291. localwav.fmt.nchannels = pcm_leuint16(&wav->fmt.nchannels);
  292. localwav.fmt.samprate = pcm_leuint32(&wav->fmt.samprate);
  293. localwav.fmt.byterate = pcm_leuint32(&wav->fmt.byterate);
  294. localwav.fmt.align = pcm_leuint16(&wav->fmt.align);
  295. localwav.fmt.bpsamp = pcm_leuint16(&wav->fmt.bpsamp);
  296. /* Find the data chunk */
  297. dchunk = &wav->data;
  298. for (; ; )
  299. {
  300. /* NOTE: The data chunk is possible to be not word-aligned if extra
  301. * chunks exist before it.
  302. */
  303. localwav.data.chunkid = pcm_leuint32(&dchunk->chunkid);
  304. localwav.data.chunklen = pcm_leuint32(&dchunk->chunklen);
  305. if (localwav.data.chunkid == WAV_DATA_CHUNKID)
  306. {
  307. break;
  308. }
  309. /* Not data chunk. Skip it. */
  310. ret += localwav.data.chunklen + 8;
  311. if (ret >= len)
  312. {
  313. /* Data chunk not found */
  314. return -EINVAL;
  315. }
  316. dchunk = (FAR const struct wav_datachunk_s *)
  317. ((uintptr_t)dchunk + localwav.data.chunklen + 8);
  318. }
  319. /* Dump the converted wave header information */
  320. pcm_dump(&localwav);
  321. /* Check if the file is a valid PCM WAV header */
  322. if (!pcm_validwav(&localwav))
  323. {
  324. return -EINVAL;
  325. }
  326. else
  327. {
  328. /* Yes... pick off the relevant format values and save then in the
  329. * device structure.
  330. */
  331. priv->samprate = localwav.fmt.samprate; /* 8000, 44100, ... */
  332. priv->byterate = localwav.fmt.byterate; /* samprate * nchannels * bpsamp / 8 */
  333. priv->align = localwav.fmt.align; /* nchannels * bpsamp / 8 */
  334. priv->bpsamp = localwav.fmt.bpsamp; /* Bits per sample: 8 bits = 8, 16 bits = 16 */
  335. priv->nchannels = localwav.fmt.nchannels; /* Mono=1, Stereo=2 */
  336. #ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
  337. /* We are going to subsample, there then are some restrictions on the
  338. * number of channels and sample sizes that we can handle.
  339. */
  340. if (priv->bpsamp != 8 && priv->bpsamp != 16)
  341. {
  342. auderr("ERROR: %d bits per sample are not supported in this "
  343. "mode\n",
  344. priv->bpsamp);
  345. return -EINVAL;
  346. }
  347. if (priv->nchannels != 1 && priv->nchannels != 2)
  348. {
  349. auderr("ERROR: %d channels are not supported in this mode\n",
  350. priv->nchannels);
  351. return -EINVAL;
  352. }
  353. DEBUGASSERT(priv->align == priv->nchannels * priv->bpsamp / 8);
  354. #endif
  355. }
  356. /* And return true if the file is a valid WAV header file */
  357. return ret;
  358. }
  359. #endif
  360. /****************************************************************************
  361. * Name: pcm_subsample_configure
  362. *
  363. * Description:
  364. * Configure to perform sub-sampling (or not) on the following audio
  365. * buffers.
  366. *
  367. ****************************************************************************/
  368. #ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
  369. static void pcm_subsample_configure(FAR struct pcm_decode_s *priv,
  370. uint8_t subsample)
  371. {
  372. audinfo("subsample: %d\n", subsample);
  373. /* Three possibilities:
  374. *
  375. * 1. We were playing normally and we have been requested to begin fast
  376. * forwarding.
  377. */
  378. if (priv->subsample == AUDIO_SUBSAMPLE_NONE)
  379. {
  380. /* Ignore request to stop fast forwarding if we are already playing
  381. * normally.
  382. */
  383. if (subsample != AUDIO_SUBSAMPLE_NONE)
  384. {
  385. audinfo("Start sub-sampling\n");
  386. /* Save the current subsample setting. Subsampling will begin on
  387. * then next audio buffer that we receive.
  388. */
  389. priv->npartial = 0;
  390. priv->skip = 0;
  391. priv->subsample = subsample;
  392. }
  393. }
  394. /* 2. We were already fast forwarding and we have been asked to return to
  395. * normal play.
  396. */
  397. else if (subsample == AUDIO_SUBSAMPLE_NONE)
  398. {
  399. audinfo("Stop sub-sampling\n");
  400. /* Indicate that we are in normal play mode. This will take effect
  401. * when the next audio buffer is received.
  402. */
  403. priv->npartial = 0;
  404. priv->skip = 0;
  405. priv->subsample = AUDIO_SUBSAMPLE_NONE;
  406. }
  407. /* 3. Were already fast forwarding and we have been asked to change the
  408. * sub-sampling rate.
  409. */
  410. else if (priv->subsample != subsample)
  411. {
  412. /* Just save the new subsample setting. It will take effect on the
  413. * next audio buffer that we receive.
  414. */
  415. priv->subsample = subsample;
  416. }
  417. }
  418. #endif
  419. /****************************************************************************
  420. * Name: pcm_subsample
  421. *
  422. * Description:
  423. * Given a newly received audio buffer, perform sub-sampling in-place in
  424. * the audio buffer. Since the sub-sampled data will always be smaller
  425. * than the original buffer, no additional buffering should be necessary.
  426. *
  427. ****************************************************************************/
  428. #ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
  429. static void pcm_subsample(FAR struct pcm_decode_s *priv,
  430. FAR struct ap_buffer_s *apb)
  431. {
  432. FAR const uint8_t *src;
  433. FAR uint8_t *dest;
  434. unsigned int destsize;
  435. unsigned int srcsize;
  436. unsigned int skipsize;
  437. unsigned int copysize;
  438. unsigned int i;
  439. /* Are we sub-sampling? */
  440. if (priv->subsample == AUDIO_SUBSAMPLE_NONE)
  441. {
  442. /* No.. do nothing to the buffer */
  443. return;
  444. }
  445. /* Yes.. we will need to subsample the newly received buffer in-place by
  446. * copying from the upper end of the buffer to the lower end.
  447. */
  448. src = &apb->samp[apb->curbyte];
  449. dest = apb->samp;
  450. srcsize = apb->nbytes - apb->curbyte;
  451. destsize = apb->nmaxbytes;
  452. /* This is the number of bytes that we need to skip between samples */
  453. skipsize = priv->align * (priv->subsample - 1);
  454. /* Let's deal with any partial samples from the last buffer */
  455. if (priv->npartial > 0)
  456. {
  457. /* Let's get an impossible corner case out of the way. What if we
  458. * received a tiny audio buffer. So small, that it (plus any previous
  459. * sample) is smaller than one sample.
  460. */
  461. if (priv->npartial + srcsize < priv->align)
  462. {
  463. /* Update the partial sample size and return the unmodified
  464. * buffer.
  465. */
  466. priv->npartial += srcsize;
  467. return;
  468. }
  469. /* We do at least have enough to complete the sample. If this data
  470. * does not resides at the correct position at the from of the audio
  471. * buffer, then we will need to copy it.
  472. */
  473. copysize = priv->align - priv->npartial;
  474. if (apb->curbyte > 0)
  475. {
  476. /* We have to copy down */
  477. for (i = 0; i < copysize; i++)
  478. {
  479. *dest++ = *src++;
  480. }
  481. }
  482. else
  483. {
  484. /* If the data is already position at the beginning of the audio
  485. * buffer, then just increment the buffer pointers around the
  486. * data.
  487. */
  488. src += copysize;
  489. dest += copysize;
  490. }
  491. /* Update the number of bytes in the working buffer and reset the
  492. * skip value
  493. */
  494. priv->npartial = 0;
  495. srcsize -= copysize;
  496. destsize -= copysize;
  497. priv->skip = skipsize;
  498. }
  499. /* Now loop until either the entire audio buffer has been sub-sampling.
  500. * This copy in place works because we know that the sub-sampled data
  501. * will always be smaller than the original data.
  502. */
  503. while (srcsize > 0)
  504. {
  505. /* Do we need to skip ahead in the buffer? */
  506. if (priv->skip > 0)
  507. {
  508. /* How much can we skip in this buffer? Depends on the smaller
  509. * of (1) the number of bytes that we need to skip and (2) the
  510. * number of bytes available in the newly received audio buffer.
  511. */
  512. copysize = MIN(priv->skip, srcsize);
  513. priv->skip -= copysize;
  514. src += copysize;
  515. srcsize -= copysize;
  516. }
  517. /* Copy the sample from the audio buffer into the working buffer. */
  518. else
  519. {
  520. /* Do we have space for the whole sample? */
  521. if (srcsize < priv->align)
  522. {
  523. /* No.. this is a partial copy */
  524. copysize = srcsize;
  525. priv->npartial = srcsize;
  526. }
  527. else
  528. {
  529. /* Copy the whole sample and re-arm the skip size */
  530. copysize = priv->align;
  531. priv->skip = skipsize;
  532. }
  533. /* Now copy the sample from the end of audio buffer
  534. * to the beginning.
  535. */
  536. for (i = 0; i < copysize; i++)
  537. {
  538. *dest++ = *src++;
  539. }
  540. /* Updates bytes available in the source buffer and bytes
  541. * remaining in the destination buffer.
  542. */
  543. srcsize -= copysize;
  544. destsize -= copysize;
  545. }
  546. }
  547. /* Update the size and offset data in the audio buffer */
  548. apb->curbyte = 0;
  549. apb->nbytes = apb->nmaxbytes - destsize;
  550. }
  551. #endif
  552. /****************************************************************************
  553. * Name: pcm_getcaps
  554. *
  555. * Description:
  556. * This method is called to retrieve the lower-half device capabilities.
  557. * It will be called with device type AUDIO_TYPE_QUERY to request the
  558. * overall capabilities, such as to determine the types of devices
  559. * supported audio formats supported, etc.
  560. * Then it may be called once or more with reported supported device types
  561. * to determine the specific capabilities of that device type
  562. * (such as MP3 encoder, WMA encoder, PCM output, etc.).
  563. *
  564. ****************************************************************************/
  565. static int pcm_getcaps(FAR struct audio_lowerhalf_s *dev, int type,
  566. FAR struct audio_caps_s *caps)
  567. {
  568. FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev;
  569. FAR struct audio_lowerhalf_s *lower;
  570. int ret;
  571. DEBUGASSERT(priv);
  572. /* Defer the operation to the lower device driver */
  573. lower = priv->lower;
  574. DEBUGASSERT(lower && lower->ops->getcaps);
  575. /* Get the capabilities of the lower-level driver */
  576. ret = lower->ops->getcaps(lower, type, caps);
  577. if (ret < 0)
  578. {
  579. auderr("ERROR: Lower getcaps() failed: %d\n", ret);
  580. return ret;
  581. }
  582. /* Modify the capabilities reported by the lower driver:
  583. * PCM is the only supported format that we will report,
  584. * regardless of what the lower driver reported.
  585. */
  586. if (caps->ac_subtype == AUDIO_TYPE_QUERY)
  587. {
  588. caps->ac_format.hw = (1 << (AUDIO_FMT_PCM - 1));
  589. }
  590. return caps->ac_len;
  591. }
  592. /****************************************************************************
  593. * Name: pcm_configure
  594. *
  595. * Description:
  596. * This method is called to bind the lower-level driver to the upper-level
  597. * driver and to configure the driver for a specific mode of
  598. * operation defined by the parameters selected in supplied device caps
  599. * structure. The lower-level device should perform any initialization
  600. * needed to prepare for operations in the specified mode. It should not,
  601. * however, process any audio data until the start method is called.
  602. *
  603. ****************************************************************************/
  604. #ifdef CONFIG_AUDIO_MULTI_SESSION
  605. static int pcm_configure(FAR struct audio_lowerhalf_s *dev,
  606. FAR void *session,
  607. FAR const struct audio_caps_s *caps)
  608. #else
  609. static int pcm_configure(FAR struct audio_lowerhalf_s *dev,
  610. FAR const struct audio_caps_s *caps)
  611. #endif
  612. {
  613. FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev;
  614. FAR struct audio_lowerhalf_s *lower;
  615. DEBUGASSERT(priv);
  616. #ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
  617. /* Pick off commands to perform sub-sampling. Those are done by this
  618. * decoder. All of configuration settings are handled by the lower level
  619. * audio driver.
  620. */
  621. if (caps->ac_type == AUDIO_TYPE_PROCESSING &&
  622. caps->ac_format.hw == AUDIO_PU_SUBSAMPLE_FORWARD)
  623. {
  624. /* Configure sub-sampling and return to avoid forwarding the
  625. * configuration to the lower level
  626. * driver.
  627. */
  628. pcm_subsample_configure(priv, caps->ac_controls.b[0]);
  629. return OK;
  630. }
  631. #endif
  632. /* Defer all other operations to the lower device driver */
  633. lower = priv->lower;
  634. DEBUGASSERT(lower && lower->ops->configure);
  635. audinfo("Defer to lower configure\n");
  636. #ifdef CONFIG_AUDIO_MULTI_SESSION
  637. return lower->ops->configure(lower, session, caps);
  638. #else
  639. return lower->ops->configure(lower, caps);
  640. #endif
  641. }
  642. /****************************************************************************
  643. * Name: pcm_shutdown
  644. *
  645. * Description:
  646. * This method is called when the driver is closed. The lower half driver
  647. * should stop processing audio data, including terminating any active
  648. * output generation. It should also disable the audio hardware and put
  649. * it into the lowest possible power usage state.
  650. *
  651. * Any enqueued Audio Pipeline Buffers that have not been
  652. * processed / dequeued should be dequeued by this function.
  653. *
  654. ****************************************************************************/
  655. static int pcm_shutdown(FAR struct audio_lowerhalf_s *dev)
  656. {
  657. FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev;
  658. FAR struct audio_lowerhalf_s *lower;
  659. DEBUGASSERT(priv);
  660. /* We are no longer streaming audio */
  661. priv->streaming = false;
  662. /* Defer the operation to the lower device driver */
  663. lower = priv->lower;
  664. DEBUGASSERT(lower && lower->ops->start);
  665. audinfo("Defer to lower shutdown\n");
  666. return lower->ops->shutdown(lower);
  667. }
  668. /****************************************************************************
  669. * Name: pcm_start
  670. *
  671. * Description:
  672. * Start audio streaming in the configured mode.
  673. * For input and synthesis devices, this means it should begin sending
  674. * streaming audio data. For output or processing type device, it means
  675. * it should begin processing of any enqueued Audio Pipeline Buffers.
  676. *
  677. ****************************************************************************/
  678. #ifdef CONFIG_AUDIO_MULTI_SESSION
  679. static int pcm_start(FAR struct audio_lowerhalf_s *dev, FAR void *session)
  680. #else
  681. static int pcm_start(FAR struct audio_lowerhalf_s *dev)
  682. #endif
  683. {
  684. FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev;
  685. FAR struct audio_lowerhalf_s *lower;
  686. DEBUGASSERT(priv);
  687. /* Defer the operation to the lower device driver */
  688. lower = priv->lower;
  689. DEBUGASSERT(lower && lower->ops->start);
  690. audinfo("Defer to lower start\n");
  691. #ifdef CONFIG_AUDIO_MULTI_SESSION
  692. return lower->ops->start(lower, session);
  693. #else
  694. return lower->ops->start(lower);
  695. #endif
  696. }
  697. /****************************************************************************
  698. * Name: pcm_stop
  699. *
  700. * Description:
  701. * Stop audio streaming and/or processing of enqueued Audio Pipeline
  702. * Buffers
  703. *
  704. ****************************************************************************/
  705. #ifndef CONFIG_AUDIO_EXCLUDE_STOP
  706. #ifdef CONFIG_AUDIO_MULTI_SESSION
  707. static int pcm_stop(FAR struct audio_lowerhalf_s *dev, FAR void *session)
  708. #else
  709. static int pcm_stop(FAR struct audio_lowerhalf_s *dev)
  710. #endif
  711. {
  712. FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev;
  713. FAR struct audio_lowerhalf_s *lower;
  714. DEBUGASSERT(priv);
  715. /* We are no longer streaming */
  716. priv->streaming = false;
  717. /* Defer the operation to the lower device driver */
  718. lower = priv->lower;
  719. DEBUGASSERT(lower && lower->ops->stop);
  720. audinfo("Defer to lower stop\n");
  721. #ifdef CONFIG_AUDIO_MULTI_SESSION
  722. return lower->ops->stop(lower, session);
  723. #else
  724. return lower->ops->stop(lower);
  725. #endif
  726. }
  727. #endif /* CONFIG_AUDIO_EXCLUDE_STOP */
  728. /****************************************************************************
  729. * Name: pcm_pause
  730. *
  731. * Description:
  732. * Pause the audio stream.
  733. * Should keep current playback context active in case a resume is issued.
  734. * Could be called and then followed by a stop.
  735. *
  736. ****************************************************************************/
  737. #ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
  738. #ifdef CONFIG_AUDIO_MULTI_SESSION
  739. static int pcm_pause(FAR struct audio_lowerhalf_s *dev, FAR void *session)
  740. #else
  741. static int pcm_pause(FAR struct audio_lowerhalf_s *dev)
  742. #endif
  743. {
  744. FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev;
  745. FAR struct audio_lowerhalf_s *lower;
  746. DEBUGASSERT(priv);
  747. /* Defer the operation to the lower device driver */
  748. lower = priv->lower;
  749. DEBUGASSERT(lower && lower->ops->pause);
  750. audinfo("Defer to lower pause\n");
  751. #ifdef CONFIG_AUDIO_MULTI_SESSION
  752. return lower->ops->pause(lower, session);
  753. #else
  754. return lower->ops->pause(lower);
  755. #endif
  756. }
  757. /****************************************************************************
  758. * Name: pcm_resume
  759. *
  760. * Description:
  761. * Resumes audio streaming after a pause.
  762. *
  763. ****************************************************************************/
  764. #ifdef CONFIG_AUDIO_MULTI_SESSION
  765. static int pcm_resume(FAR struct audio_lowerhalf_s *dev, FAR void *session)
  766. #else
  767. static int pcm_resume(FAR struct audio_lowerhalf_s *dev)
  768. #endif
  769. {
  770. FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev;
  771. FAR struct audio_lowerhalf_s *lower;
  772. DEBUGASSERT(priv);
  773. /* Defer the operation to the lower device driver */
  774. lower = priv->lower;
  775. DEBUGASSERT(lower && lower->ops->resume);
  776. audinfo("Defer to lower resume\n");
  777. #ifdef CONFIG_AUDIO_MULTI_SESSION
  778. return lower->ops->resume(lower, session);
  779. #else
  780. return lower->ops->resume(lower);
  781. #endif
  782. }
  783. #endif /* CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME */
  784. /****************************************************************************
  785. * Name: pcm_allocbuffer
  786. *
  787. * Description:
  788. * Allocate an audio pipeline buffer. This routine provides the
  789. * lower-half driver with the opportunity to perform special buffer
  790. * allocation if needed, such as allocating from a specific memory
  791. * region (DMA-able, etc.). If not supplied, then the top-half
  792. * driver will perform a standard kumm_malloc using normal user-space
  793. * memory region.
  794. *
  795. ****************************************************************************/
  796. static int pcm_allocbuffer(FAR struct audio_lowerhalf_s *dev,
  797. FAR struct audio_buf_desc_s *apb)
  798. {
  799. FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev;
  800. FAR struct audio_lowerhalf_s *lower;
  801. DEBUGASSERT(priv);
  802. /* Defer the operation to the lower device driver */
  803. lower = priv->lower;
  804. DEBUGASSERT(lower && lower->ops->allocbuffer);
  805. audinfo("Defer to lower allocbuffer\n");
  806. return lower->ops->allocbuffer(lower, apb);
  807. }
  808. /****************************************************************************
  809. * Name: pcm_freebuffer
  810. *
  811. * Description:
  812. * Free an audio pipeline buffer. If the lower-level driver provides an
  813. * allocbuffer routine, it should also provide the freebuffer routine to
  814. * perform the free operation.
  815. *
  816. ****************************************************************************/
  817. static int pcm_freebuffer(FAR struct audio_lowerhalf_s *dev,
  818. FAR struct audio_buf_desc_s *apb)
  819. {
  820. FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev;
  821. FAR struct audio_lowerhalf_s *lower;
  822. DEBUGASSERT(priv);
  823. /* Defer the operation to the lower device driver */
  824. lower = priv->lower;
  825. DEBUGASSERT(lower && lower->ops->freebuffer);
  826. audinfo("Defer to lower freebuffer, apb=%p\n", apb);
  827. return lower->ops->freebuffer(lower, apb);
  828. }
  829. /****************************************************************************
  830. * Name: pcm_enqueuebuffer
  831. *
  832. * Description:
  833. * Enqueue a buffer for processing. This is a non-blocking enqueue
  834. * operation. If the lower-half driver's buffer queue is full, then it
  835. * should return an error code of -ENOMEM, and the upper-half driver can
  836. * decide to either block the calling thread or deal with it in a non-
  837. * blocking manner.
  838. *
  839. * For each call to enqueuebuffer, the lower-half driver must call
  840. * audio_dequeuebuffer when it is finished processing the bufferr, passing
  841. * the previously enqueued apb and a dequeue status so that the upper-half
  842. * driver can decide if a waiting thread needs to be release, if the
  843. * dequeued buffer should be passed to the next block in the Audio
  844. * Pipeline, etc.
  845. *
  846. ****************************************************************************/
  847. static int pcm_enqueuebuffer(FAR struct audio_lowerhalf_s *dev,
  848. FAR struct ap_buffer_s *apb)
  849. {
  850. FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev;
  851. FAR struct audio_lowerhalf_s *lower;
  852. apb_samp_t bytesleft;
  853. ssize_t headersize;
  854. int ret;
  855. DEBUGASSERT(priv);
  856. audinfo("Received buffer %p, streaming=%d\n", apb, priv->streaming);
  857. lower = priv->lower;
  858. DEBUGASSERT(lower && lower->ops->enqueuebuffer && lower->ops->configure);
  859. /* Are we streaming yet? */
  860. if (priv->streaming)
  861. {
  862. /* Yes, we are streaming */
  863. /* Check for the last audio buffer in the stream */
  864. if ((apb->flags & AUDIO_APB_FINAL) != 0)
  865. {
  866. /* Yes.. then we are no longer streaming */
  867. priv->streaming = false;
  868. }
  869. #ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
  870. audinfo("Received: apb=%p curbyte=%d nbytes=%d flags=%04x\n",
  871. apb, apb->curbyte, apb->nbytes, apb->flags);
  872. /* Perform any necessary sub-sampling operations */
  873. pcm_subsample(priv, apb);
  874. #endif
  875. /* Then give the audio buffer to the lower driver */
  876. audinfo("Pass to lower enqueuebuffer: apb=%p curbyte=%d nbytes=%d\n",
  877. apb, apb->curbyte, apb->nbytes);
  878. return lower->ops->enqueuebuffer(lower, apb);
  879. }
  880. /* No.. then this must be the first buffer that we have seen (since we
  881. * will error out out if the first buffer is smaller than the WAV file
  882. * header. There is no attempt to reconstruct the full header from
  883. * fragments in multiple, tiny audio buffers).
  884. */
  885. bytesleft = apb->nbytes - apb->curbyte;
  886. audinfo("curbyte=%d nbytes=%d nmaxbytes=%d bytesleft=%d\n",
  887. apb->curbyte, apb->nbytes, apb->nmaxbytes, bytesleft);
  888. /* Parse and verify the candidate PCM WAV file header */
  889. #ifndef CONFIG_AUDIO_FORMAT_RAW
  890. headersize = pcm_parsewav(priv, &apb->samp[apb->curbyte], bytesleft);
  891. if (headersize > 0)
  892. {
  893. struct audio_caps_s caps;
  894. /* Configure the lower level for the number of channels, bitrate,
  895. * and sample bitwidth.
  896. */
  897. DEBUGASSERT(priv->samprate < 65535);
  898. caps.ac_len = sizeof(struct audio_caps_s);
  899. caps.ac_type = AUDIO_TYPE_OUTPUT;
  900. caps.ac_channels = priv->nchannels;
  901. caps.ac_controls.hw[0] = (uint16_t)priv->samprate;
  902. caps.ac_controls.b[2] = priv->bpsamp;
  903. #ifdef CONFIG_AUDIO_MULTI_SESSION
  904. ret = lower->ops->configure(lower, priv->session, &caps);
  905. #else
  906. ret = lower->ops->configure(lower, &caps);
  907. #endif
  908. if (ret < 0)
  909. {
  910. auderr("ERROR: Failed to set PCM configuration: %d\n", ret);
  911. return ret;
  912. }
  913. /* Bump up the data offset */
  914. apb->curbyte += headersize;
  915. #endif
  916. #ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
  917. audinfo("Begin streaming: apb=%p curbyte=%d nbytes=%d\n",
  918. apb, apb->curbyte, apb->nbytes);
  919. /* Perform any necessary sub-sampling operations */
  920. pcm_subsample(priv, apb);
  921. #endif
  922. /* Then give the audio buffer to the lower driver */
  923. audinfo(
  924. "Pass to lower enqueuebuffer: apb=%p curbyte=%d nbytes=%d\n",
  925. apb, apb->curbyte, apb->nbytes);
  926. ret = lower->ops->enqueuebuffer(lower, apb);
  927. if (ret == OK)
  928. {
  929. /* Now we are streaming. Unless for some reason there is only
  930. * one audio buffer in the audio stream. In that case, this
  931. * will be marked as the final buffer
  932. */
  933. priv->streaming = ((apb->flags & AUDIO_APB_FINAL) == 0);
  934. return OK;
  935. }
  936. /* The normal protocol for streaming errors is as follows:
  937. *
  938. * (1) Fail the enqueueing by returned a negated error value. The
  939. * upper level then knows that this buffer was not queue.
  940. * (2) Return all queued buffers to the caller using the
  941. * AUDIO_CALLBACK_DEQUEUE callback
  942. * (3) Terminate playing using the AUDIO_CALLBACK_COMPLETE
  943. * callback.
  944. *
  945. * In this case we fail on the very first buffer and we need only
  946. * do (1) and (3).
  947. */
  948. #ifdef CONFIG_AUDIO_MULTI_SESSION
  949. priv->export.upper(priv->export.priv, AUDIO_CALLBACK_COMPLETE,
  950. NULL, OK, NULL);
  951. #else
  952. priv->export.upper(priv->export.priv, AUDIO_CALLBACK_COMPLETE,
  953. NULL, OK);
  954. #endif
  955. #ifndef CONFIG_AUDIO_FORMAT_RAW
  956. }
  957. /* This is not a WAV file! */
  958. auderr("ERROR: Invalid PCM WAV file\n");
  959. #endif
  960. return -EINVAL;
  961. }
  962. /****************************************************************************
  963. * Name: pcm_cancelbuffer
  964. *
  965. * Description:
  966. * Cancel a previously enqueued buffer.
  967. *
  968. ****************************************************************************/
  969. static int pcm_cancelbuffer(FAR struct audio_lowerhalf_s *dev,
  970. FAR struct ap_buffer_s *apb)
  971. {
  972. FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev;
  973. FAR struct audio_lowerhalf_s *lower;
  974. DEBUGASSERT(priv);
  975. /* Defer the operation to the lower device driver */
  976. lower = priv->lower;
  977. DEBUGASSERT(lower && lower->ops->cancelbuffer);
  978. audinfo("Defer to lower cancelbuffer, apb=%p\n", apb);
  979. return lower->ops->cancelbuffer(lower, apb);
  980. }
  981. /****************************************************************************
  982. * Name: pcm_ioctl
  983. *
  984. * Description:
  985. * Lower-half logic may support platform-specific ioctl commands.
  986. *
  987. ****************************************************************************/
  988. static int pcm_ioctl(FAR struct audio_lowerhalf_s *dev, int cmd,
  989. unsigned long arg)
  990. {
  991. FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev;
  992. FAR struct audio_lowerhalf_s *lower;
  993. DEBUGASSERT(priv);
  994. /* Defer the operation to the lower device driver */
  995. lower = priv->lower;
  996. DEBUGASSERT(lower && lower->ops->ioctl);
  997. audinfo("Defer to lower ioctl, cmd=%d arg=%ld\n", cmd, arg);
  998. return lower->ops->ioctl(lower, cmd, arg);
  999. }
  1000. /****************************************************************************
  1001. * Name: pcm_reserve
  1002. *
  1003. * Description:
  1004. * Reserve a session (may only be one per device or may be multiple) for
  1005. * use by a client. Client software can open audio devices and issue
  1006. * AUDIOIOC_GETCAPS calls freely, but other operations require a
  1007. * reservation. A session reservation will assign a context that must
  1008. * be passed with
  1009. *
  1010. ****************************************************************************/
  1011. #ifdef CONFIG_AUDIO_MULTI_SESSION
  1012. static int pcm_reserve(FAR struct audio_lowerhalf_s *dev, FAR void **session)
  1013. #else
  1014. static int pcm_reserve(FAR struct audio_lowerhalf_s *dev)
  1015. #endif
  1016. {
  1017. FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev;
  1018. FAR struct audio_lowerhalf_s *lower;
  1019. int ret;
  1020. #ifdef CONFIG_AUDIO_MULTI_SESSION
  1021. DEBUGASSERT(priv && session);
  1022. #else
  1023. DEBUGASSERT(priv);
  1024. #endif
  1025. /* It is not necessary to reserve the upper half. What we really need to
  1026. * do is to reserved the lower device driver for exclusive use by the PCM
  1027. * decoder. That effectively reserves the upper PCM decoder along with
  1028. * the lower driver (which is then not available for use by other
  1029. * decoders).
  1030. *
  1031. * We do, however, need to remember the session returned by the lower
  1032. * level.
  1033. */
  1034. lower = priv->lower;
  1035. DEBUGASSERT(lower && lower->ops->reserve);
  1036. audinfo("Defer to lower reserve\n");
  1037. #ifdef CONFIG_AUDIO_MULTI_SESSION
  1038. ret = lower->ops->reserve(lower, &priv->session);
  1039. /* Return a copy of the session to the caller */
  1040. *session = priv->session;
  1041. #else
  1042. ret = lower->ops->reserve(lower);
  1043. #endif
  1044. return ret;
  1045. }
  1046. /****************************************************************************
  1047. * Name: pcm_release
  1048. *
  1049. * Description:
  1050. * Release a session.
  1051. *
  1052. ****************************************************************************/
  1053. #ifdef CONFIG_AUDIO_MULTI_SESSION
  1054. static int pcm_release(FAR struct audio_lowerhalf_s *dev, FAR void *session)
  1055. #else
  1056. static int pcm_release(FAR struct audio_lowerhalf_s *dev)
  1057. #endif
  1058. {
  1059. FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev;
  1060. FAR struct audio_lowerhalf_s *lower;
  1061. DEBUGASSERT(priv);
  1062. /* Release the lower driver. It is then available for use by other
  1063. * decoders (and we cannot use the lower driver either unless we re-
  1064. * reserve it).
  1065. */
  1066. lower = priv->lower;
  1067. DEBUGASSERT(lower && lower->ops->release);
  1068. audinfo("Defer to lower release\n");
  1069. #ifdef CONFIG_AUDIO_MULTI_SESSION
  1070. return lower->ops->release(lower, session);
  1071. #else
  1072. return lower->ops->release(lower);
  1073. #endif
  1074. }
  1075. /****************************************************************************
  1076. * Name: pcm_callback
  1077. *
  1078. * Description:
  1079. * Lower-to-upper level callback for buffer dequeueing.
  1080. *
  1081. * Input Parameters:
  1082. * priv - The value of the 'priv' field from out audio_lowerhalf_s.
  1083. *
  1084. * Returned Value:
  1085. * None
  1086. *
  1087. ****************************************************************************/
  1088. #ifdef CONFIG_AUDIO_MULTI_SESSION
  1089. static void pcm_callback(FAR void *arg, uint16_t reason,
  1090. FAR struct ap_buffer_s *apb, uint16_t status,
  1091. FAR void *session)
  1092. #else
  1093. static void pcm_callback(FAR void *arg, uint16_t reason,
  1094. FAR struct ap_buffer_s *apb, uint16_t status)
  1095. #endif
  1096. {
  1097. FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)arg;
  1098. DEBUGASSERT(priv && priv->export.upper);
  1099. /* The buffer belongs to an upper level. Just forward the event to
  1100. * the next level up.
  1101. */
  1102. #ifdef CONFIG_AUDIO_MULTI_SESSION
  1103. priv->export.upper(priv->export.priv, reason, apb, status, session);
  1104. #else
  1105. priv->export.upper(priv->export.priv, reason, apb, status);
  1106. #endif
  1107. }
  1108. /****************************************************************************
  1109. * Public Functions
  1110. ****************************************************************************/
  1111. /****************************************************************************
  1112. * Name: pcm_decode_initialize
  1113. *
  1114. * Description:
  1115. * Initialize the PCM device. The PCM device accepts and contains a
  1116. * low-level audio DAC-type device. It then returns a new audio lower
  1117. * half interface at adds a PCM decoding from end to the low-level
  1118. * audio device
  1119. *
  1120. * Input Parameters:
  1121. * dev - A reference to the low-level audio DAC-type device to contain.
  1122. *
  1123. * Returned Value:
  1124. * On success, a new audio device instance is returned that wraps the
  1125. * low-level device and provides a PCM decoding front end. NULL is
  1126. * returned on failure.
  1127. *
  1128. ****************************************************************************/
  1129. FAR struct audio_lowerhalf_s *
  1130. pcm_decode_initialize(FAR struct audio_lowerhalf_s *dev)
  1131. {
  1132. FAR struct pcm_decode_s *priv;
  1133. FAR struct audio_ops_s *ops;
  1134. /* Allocate an instance of our private data structure */
  1135. priv = (FAR struct pcm_decode_s *)kmm_zalloc(sizeof(struct pcm_decode_s));
  1136. if (!priv)
  1137. {
  1138. auderr("ERROR: Failed to allocate driver structure\n");
  1139. return NULL;
  1140. }
  1141. /* Initialize our private data structure. Since kmm_zalloc() was used for
  1142. * the allocation, we need to initialize only non-zero, non-NULL, non-
  1143. * false fields.
  1144. */
  1145. /* Setup our operations */
  1146. ops = &priv->ops;
  1147. ops->getcaps = pcm_getcaps;
  1148. ops->configure = pcm_configure;
  1149. ops->shutdown = pcm_shutdown;
  1150. ops->start = pcm_start;
  1151. #ifndef CONFIG_AUDIO_EXCLUDE_STOP
  1152. ops->stop = pcm_stop;
  1153. #endif
  1154. #ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
  1155. ops->pause = pcm_pause;
  1156. ops->resume = pcm_resume;
  1157. #endif
  1158. if (dev->ops->allocbuffer)
  1159. {
  1160. DEBUGASSERT(dev->ops->freebuffer);
  1161. ops->allocbuffer = pcm_allocbuffer;
  1162. ops->freebuffer = pcm_freebuffer;
  1163. }
  1164. ops->enqueuebuffer = pcm_enqueuebuffer;
  1165. ops->cancelbuffer = pcm_cancelbuffer;
  1166. ops->ioctl = pcm_ioctl;
  1167. ops->reserve = pcm_reserve;
  1168. ops->release = pcm_release;
  1169. /* Set up our struct audio_lower_half that we will register with the
  1170. * system. The registration process will fill in the priv->export.upper
  1171. * and priv fields with the correct callback information.
  1172. */
  1173. priv->export.ops = &priv->ops;
  1174. /* Save the struct audio_lower_half of the low-level audio device. Set
  1175. * out callback information for the lower-level audio device. Our
  1176. * callback will simply forward to the upper callback.
  1177. */
  1178. priv->lower = dev;
  1179. dev->upper = pcm_callback;
  1180. dev->priv = priv;
  1181. return &priv->export;
  1182. }
  1183. #endif /* CONFIG_AUDIO && CONFIG_AUDIO_FORMAT_PCM */