source: mainline/uspace/app/dplay/dplay.c@ eaa1c28

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since eaa1c28 was eaa1c28, checked in by Jan Vesely <jano.vesely@…>, 14 years ago

dplay: Add wav files playback.

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/*
2 * Copyright (c) 2011 Jan Vesely
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup dplay
30 * @{
31 */
32/**
33 * @file PCM playback audio devices
34 */
35
36#include <assert.h>
37#include <errno.h>
38#include <str_error.h>
39#include <str.h>
40#include <devman.h>
41#include <audio_pcm_buffer_iface.h>
42#include <stdio.h>
43#include <sys/mman.h>
44#include <sys/time.h>
45
46#include <stdio.h>
47
48#include "wave.h"
49
50#define DEFAULT_DEVICE "/hw/pci0/00:01.0/sb16/dsp"
51
52static void play(async_exch_t *device, unsigned buffer_id,
53 void *buffer, size_t size, FILE *source,
54 unsigned sampling_rate, unsigned sample_size, unsigned channels, bool sign)
55{
56 assert(device);
57 const size_t half_buf = size / 2;
58
59 /* Time to play half the buffer. */
60 const unsigned interval = 1000000 /
61 (sampling_rate / (half_buf / (channels * (sample_size / 8))));
62 printf("Time to play half buffer: %zu us.\n", interval);
63 /* Initialize buffer. */
64 const size_t bytes = fread(buffer, sizeof(uint8_t), size, source);
65 if (bytes != size)
66 return;
67
68 struct timeval time;
69 gettimeofday(&time, NULL);
70 printf("Starting playback.\n");
71 int ret = audio_pcm_buffer_start_playback(device, buffer_id,
72 sampling_rate, sample_size, channels, sign);
73 if (ret != EOK) {
74 printf("Failed to start playback: %s.\n", str_error(ret));
75 return;
76 }
77 void *buffer_place = buffer;
78 while (true) {
79 tv_add(&time, interval); /* Next update point */
80 struct timeval current;
81 gettimeofday(&current, NULL);
82
83 const suseconds_t delay = tv_sub(&time, &current);
84 if (delay > 0)
85 usleep(delay);
86 const size_t bytes =
87 fread(buffer, sizeof(uint8_t), half_buf, source);
88 if (bytes == 0)
89 break;
90 if (bytes < half_buf) {
91 bzero(buffer_place + bytes, half_buf - bytes);
92 }
93 if (buffer_place == buffer) {
94 buffer_place = buffer + half_buf;
95 } else {
96 buffer_place = buffer;
97 }
98 }
99
100 printf("Stopping playback.\n");
101 ret = audio_pcm_buffer_stop_playback(device, buffer_id);
102 if (ret != EOK) {
103 printf("Failed to stop playback: %s.\n", str_error(ret));
104 }
105}
106
107int main(int argc, char *argv[])
108{
109 const char *device = DEFAULT_DEVICE;
110 const char *file;
111 switch (argc) {
112 case 2:
113 file = argv[1];
114 break;
115 case 3:
116 device = argv[1];
117 file = argv[2];
118 break;
119 default:
120 printf("Usage: %s [device] file.\n", argv[0]);
121 return 1;
122 }
123
124 devman_handle_t pcm_handle;
125 int ret = devman_fun_get_handle(device, &pcm_handle, 0);
126 if (ret != EOK) {
127 printf("Failed to get device(%s) handle: %s.\n",
128 device, str_error(ret));
129 return 1;
130 }
131
132 async_sess_t *session = devman_device_connect(
133 EXCHANGE_ATOMIC, pcm_handle, IPC_FLAG_BLOCKING);
134 if (!session) {
135 printf("Failed to connect to device.\n");
136 return 1;
137 }
138
139 async_exch_t *exch = async_exchange_begin(session);
140 if (!exch) {
141 printf("Failed to start session exchange.\n");
142 async_hangup(session);
143 return 1;
144 }
145 const char* info;
146 ret = audio_pcm_buffer_get_info_str(exch, &info);
147 if (ret != EOK) {
148 printf("Failed to get PCM info.\n");
149 async_exchange_end(exch);
150 async_hangup(session);
151 return 1;
152 }
153 printf("Playing on %s.\n", info);
154 free(info);
155
156 void *buffer = NULL;
157 size_t size = 0;
158 unsigned id = 0;
159 ret = audio_pcm_buffer_get_buffer(exch, &buffer, &size, &id);
160 if (ret != EOK) {
161 printf("Failed to get PCM buffer: %s.\n", str_error(ret));
162 async_exchange_end(exch);
163 async_hangup(session);
164 return 1;
165 }
166 printf("Buffer (%u): %p %zu.\n", id, buffer, size);
167
168 FILE *source = fopen(file, "rb");
169 if (source == NULL) {
170 printf("Failed to open %s.\n", file);
171 munmap(buffer, size);
172 audio_pcm_buffer_release_buffer(exch, id);
173 async_exchange_end(exch);
174 async_hangup(session);
175 return 1;
176 }
177 wave_header_t header;
178 fread(&header, sizeof(header), 1, source);
179 unsigned rate, sample_size, channels;
180 bool sign;
181 const char *error;
182 ret = wav_parse_header(&header, NULL, NULL, &rate, &sample_size,
183 &channels, &sign, &error);
184 if (ret != EOK) {
185 printf("Error parsing wav header: %s.\n", error);
186 fclose(source);
187 munmap(buffer, size);
188 audio_pcm_buffer_release_buffer(exch, id);
189 async_exchange_end(exch);
190 async_hangup(session);
191 return 1;
192 }
193
194 play(exch, id, buffer, size, source, rate, sample_size, channels, sign);
195
196 munmap(buffer, size);
197 audio_pcm_buffer_release_buffer(exch, id);
198 async_exchange_end(exch);
199 async_hangup(session);
200 return 0;
201}
202/**
203 * @}
204 */
Note: See TracBrowser for help on using the repository browser.