2 * Copyright (c) 2006-2011 Ed Schouten <ed@80386.nl>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * @file audio_format_vorbis.c
28 * @brief Ogg Vorbis decompression routines.
33 #include <vorbis/codec.h>
34 #include <vorbis/vorbisfile.h>
36 #include "audio_file.h"
37 #include "audio_format.h"
38 #include "audio_output.h"
41 * @brief Read tags from Ogg Vorbis file and store them in the audio
45 vorbis_read_comments(struct audio_file
*fd
)
47 OggVorbis_File
*vfp
= fd
->drv_data
;
48 struct vorbis_comment
*cmt
;
52 if ((cmt
= ov_comment(vfp
, -1)) == NULL
)
55 for (i
= 0; i
< cmt
->comments
; i
++) {
56 tag
= cmt
->user_comments
[i
];
58 if (g_ascii_strncasecmp(tag
, "artist=", 7) == 0)
59 fd
->artist
= g_strdup(tag
+ 7);
60 else if (g_ascii_strncasecmp(tag
, "title=", 6) == 0)
61 fd
->title
= g_strdup(tag
+ 6);
62 #ifdef BUILD_SCROBBLER
63 else if (g_ascii_strncasecmp(tag
, "album=", 6) == 0)
64 fd
->album
= g_strdup(tag
+ 6);
65 #endif /* BUILD_SCROBBLER */
70 vorbis_open(struct audio_file
*fd
, const char *ext
)
80 vfp
= g_slice_new(OggVorbis_File
);
81 if (ov_open(fd
->fp
, vfp
, NULL
, 0) != 0) {
82 g_slice_free(OggVorbis_File
, vfp
);
86 info
= ov_info(vfp
, -1);
89 fd
->srate
= info
->rate
;
90 fd
->channels
= 2; /* XXX */
91 fd
->time_len
= ov_time_total(vfp
, -1);
93 vorbis_read_comments(fd
);
99 vorbis_close(struct audio_file
*fd
)
101 OggVorbis_File
*vfp
= fd
->drv_data
;
104 g_slice_free(OggVorbis_File
, vfp
);
106 /* libvorbisfile already closes the file for us */
111 vorbis_read(struct audio_file
*fd
, int16_t *buf
, size_t len
)
113 OggVorbis_File
*vfp
= fd
->drv_data
;
116 char *out
= (char *)buf
;
118 len
*= sizeof(int16_t);
120 /* Return 16 bits signed native endian */
122 #if G_BYTE_ORDER == G_BIG_ENDIAN
123 rlen
= ov_read(vfp
, out
+ ret
, len
- ret
, 1, 2, 1, NULL
);
124 #else /* G_BYTE_ORDER != G_BIG_ENDIAN */
125 rlen
= ov_read(vfp
, out
+ ret
, len
- ret
, 0, 2, 1, NULL
);
126 #endif /* G_BYTE_ORDER == G_BIG_ENDIAN */
131 fd
->time_cur
= ov_time_tell(vfp
);
133 return (ret
/ sizeof(int16_t));
137 vorbis_seek(struct audio_file
*fd
, int len
, int rel
)
140 OggVorbis_File
*vfp
= fd
->drv_data
;
144 /* Perform a relative seek. */
145 npos
+= ov_time_tell(vfp
);
148 npos
= CLAMP(npos
, 0, ov_time_total(vfp
, -1));
150 ov_time_seek(vfp
, npos
);
151 fd
->time_cur
= ov_time_tell(vfp
);