]> code.delx.au - pulseaudio/blob - src/pulsecore/sound-file.c
Merge commit 'origin/master-tx'
[pulseaudio] / src / pulsecore / sound-file.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2.1 of the License,
9 or (at your option) any later version.
10
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <errno.h>
30
31 #include <sndfile.h>
32
33 #include <pulse/sample.h>
34 #include <pulsecore/log.h>
35 #include <pulsecore/macro.h>
36 #include <pulsecore/core-error.h>
37 #include <pulsecore/core-util.h>
38
39 #include "sound-file.h"
40 #include "core-scache.h"
41
42 int pa_sound_file_load(
43 pa_mempool *pool,
44 const char *fname,
45 pa_sample_spec *ss,
46 pa_channel_map *map,
47 pa_memchunk *chunk) {
48
49 SNDFILE *sf = NULL;
50 SF_INFO sfinfo;
51 int ret = -1;
52 size_t l;
53 sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames) = NULL;
54 void *ptr = NULL;
55 int fd;
56
57 pa_assert(fname);
58 pa_assert(ss);
59 pa_assert(chunk);
60
61 pa_memchunk_reset(chunk);
62 memset(&sfinfo, 0, sizeof(sfinfo));
63
64 if ((fd = open(fname, O_RDONLY
65 #ifdef O_NOCTTY
66 |O_NOCTTY
67 #endif
68 )) < 0) {
69 pa_log("Failed to open file %s: %s", fname, pa_cstrerror(errno));
70 goto finish;
71 }
72
73 #ifdef HAVE_POSIX_FADVISE
74 if (posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL) < 0) {
75 pa_log_warn("POSIX_FADV_SEQUENTIAL failed: %s", pa_cstrerror(errno));
76 goto finish;
77 } else
78 pa_log_debug("POSIX_FADV_SEQUENTIAL succeeded.");
79 #endif
80
81 if (!(sf = sf_open_fd(fd, SFM_READ, &sfinfo, 1))) {
82 pa_log("Failed to open file %s", fname);
83 pa_close(fd);
84 goto finish;
85 }
86
87 switch (sfinfo.format & SF_FORMAT_SUBMASK) {
88 case SF_FORMAT_PCM_16:
89 case SF_FORMAT_PCM_U8:
90 case SF_FORMAT_PCM_S8:
91 ss->format = PA_SAMPLE_S16NE;
92 readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *_ptr, sf_count_t frames)) sf_readf_short;
93 break;
94
95 case SF_FORMAT_ULAW:
96 ss->format = PA_SAMPLE_ULAW;
97 break;
98
99 case SF_FORMAT_ALAW:
100 ss->format = PA_SAMPLE_ALAW;
101 break;
102
103 case SF_FORMAT_FLOAT:
104 case SF_FORMAT_DOUBLE:
105 default:
106 ss->format = PA_SAMPLE_FLOAT32NE;
107 readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *_ptr, sf_count_t frames)) sf_readf_float;
108 break;
109 }
110
111 ss->rate = (uint32_t) sfinfo.samplerate;
112 ss->channels = (uint8_t) sfinfo.channels;
113
114 if (!pa_sample_spec_valid(ss)) {
115 pa_log("Unsupported sample format in file %s", fname);
116 goto finish;
117 }
118
119 if (map)
120 pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_DEFAULT);
121
122 if ((l = pa_frame_size(ss) * (size_t) sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) {
123 pa_log("File too large");
124 goto finish;
125 }
126
127 chunk->memblock = pa_memblock_new(pool, l);
128 chunk->index = 0;
129 chunk->length = l;
130
131 ptr = pa_memblock_acquire(chunk->memblock);
132
133 if ((readf_function && readf_function(sf, ptr, sfinfo.frames) != sfinfo.frames) ||
134 (!readf_function && sf_read_raw(sf, ptr, (sf_count_t) l) != (sf_count_t) l)) {
135 pa_log("Premature file end");
136 goto finish;
137 }
138
139 ret = 0;
140
141 finish:
142
143 if (sf)
144 sf_close(sf);
145
146 if (ptr)
147 pa_memblock_release(chunk->memblock);
148
149 if (ret != 0 && chunk->memblock)
150 pa_memblock_unref(chunk->memblock);
151
152 return ret;
153 }
154
155 int pa_sound_file_too_big_to_cache(const char *fname) {
156
157 SNDFILE*sf = NULL;
158 SF_INFO sfinfo;
159 pa_sample_spec ss;
160
161 pa_assert(fname);
162
163 if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) {
164 pa_log("Failed to open file %s", fname);
165 return -1;
166 }
167
168 sf_close(sf);
169
170 switch (sfinfo.format & SF_FORMAT_SUBMASK) {
171 case SF_FORMAT_PCM_16:
172 case SF_FORMAT_PCM_U8:
173 case SF_FORMAT_PCM_S8:
174 ss.format = PA_SAMPLE_S16NE;
175 break;
176
177 case SF_FORMAT_ULAW:
178 ss.format = PA_SAMPLE_ULAW;
179 break;
180
181 case SF_FORMAT_ALAW:
182 ss.format = PA_SAMPLE_ALAW;
183 break;
184
185 case SF_FORMAT_DOUBLE:
186 case SF_FORMAT_FLOAT:
187 default:
188 ss.format = PA_SAMPLE_FLOAT32NE;
189 break;
190 }
191
192 ss.rate = (uint32_t) sfinfo.samplerate;
193 ss.channels = (uint8_t) sfinfo.channels;
194
195 if (!pa_sample_spec_valid(&ss)) {
196 pa_log("Unsupported sample format in file %s", fname);
197 return -1;
198 }
199
200 if ((pa_frame_size(&ss) * (size_t) sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) {
201 pa_log("File too large: %s", fname);
202 return 1;
203 }
204
205 return 0;
206 }