forked from len0rd/rockbox
Add first version of WAV playback to iRiver - only 16-bit Stereo 44.1KHz files supported.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6654 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
d30f1100ec
commit
3c2c2f59f4
2 changed files with 183 additions and 1 deletions
|
|
@ -598,7 +598,7 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
|
||||||
int rc, i;
|
int rc, i;
|
||||||
int copy_n;
|
int copy_n;
|
||||||
/* Used by the FLAC metadata parser */
|
/* Used by the FLAC metadata parser */
|
||||||
unsigned long totalsamples;
|
unsigned long totalsamples,bytespersample,channels,bitspersample,numbytes;
|
||||||
unsigned char* buf;
|
unsigned char* buf;
|
||||||
|
|
||||||
if (track_count >= MAX_TRACK)
|
if (track_count >= MAX_TRACK)
|
||||||
|
|
@ -677,6 +677,57 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
|
||||||
tracks[track_widx].taginfo_ready = true;
|
tracks[track_widx].taginfo_ready = true;
|
||||||
break ;
|
break ;
|
||||||
|
|
||||||
|
case AFMT_PCM_WAV:
|
||||||
|
/* Use the trackname part of the id3 structure as a temporary buffer */
|
||||||
|
buf=tracks[track_widx].id3.path;
|
||||||
|
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
|
rc = read(fd, buf, 44);
|
||||||
|
if (rc < 44) {
|
||||||
|
close(fd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((memcmp(buf,"RIFF",4)!=0) ||
|
||||||
|
(memcmp(&buf[8],"WAVEfmt",7)!=0)) {
|
||||||
|
logf("%s is not a WAV file\n",trackname);
|
||||||
|
close(fd);
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIX: Correctly parse WAV header - we assume canonical
|
||||||
|
44-byte header */
|
||||||
|
|
||||||
|
bitspersample=buf[34];
|
||||||
|
channels=buf[22];
|
||||||
|
|
||||||
|
if ((bitspersample!=16) || (channels != 2)) {
|
||||||
|
logf("Unsupported WAV file - %d bitspersample, %d channels\n",
|
||||||
|
bitspersample,channels);
|
||||||
|
close(fd);
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bytespersample=((bitspersample/8)*channels);
|
||||||
|
numbytes=(buf[40]|(buf[41]<<8)|(buf[42]<<16)|(buf[43]<<24));
|
||||||
|
totalsamples=numbytes/bytespersample;
|
||||||
|
|
||||||
|
tracks[track_widx].id3.vbr=false; /* All WAV files are CBR */
|
||||||
|
tracks[track_widx].id3.filesize=filesize(fd);
|
||||||
|
tracks[track_widx].id3.frequency=buf[24]|(buf[25]<<8)|(buf[26]<<16)|(buf[27]<<24);
|
||||||
|
|
||||||
|
/* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */
|
||||||
|
tracks[track_widx].id3.length=(totalsamples/tracks[track_widx].id3.frequency)*1000;
|
||||||
|
tracks[track_widx].id3.bitrate=(tracks[track_widx].id3.frequency*bytespersample)/1024;
|
||||||
|
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
strncpy(tracks[track_widx].id3.path,trackname,sizeof(tracks[track_widx].id3.path));
|
||||||
|
tracks[track_widx].taginfo_ready = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
case AFMT_FLAC:
|
case AFMT_FLAC:
|
||||||
/* A simple parser to read vital metadata from a FLAC file - length, frequency, bitrate etc. */
|
/* A simple parser to read vital metadata from a FLAC file - length, frequency, bitrate etc. */
|
||||||
/* This code should either be moved to a seperate file, or discarded in favour of the libFLAC code */
|
/* This code should either be moved to a seperate file, or discarded in favour of the libFLAC code */
|
||||||
|
|
|
||||||
131
apps/plugins/codecwav.c
Normal file
131
apps/plugins/codecwav.c
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 Dave Chapman
|
||||||
|
*
|
||||||
|
* All files in this archive are subject to the GNU General Public License.
|
||||||
|
* See the file COPYING in the source tree root for full license agreement.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "plugin.h"
|
||||||
|
#include "playback.h"
|
||||||
|
#include "lib/codeclib.h"
|
||||||
|
|
||||||
|
#ifndef SIMULATOR
|
||||||
|
extern char iramcopy[];
|
||||||
|
extern char iramstart[];
|
||||||
|
extern char iramend[];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* This is probably a waste of IRAM, but why not? */
|
||||||
|
static unsigned char wavbuf[16384] IDATA_ATTR;
|
||||||
|
|
||||||
|
/* this is the plugin entry point */
|
||||||
|
enum plugin_status plugin_start(struct plugin_api* api, void* parm)
|
||||||
|
{
|
||||||
|
struct plugin_api* rb = (struct plugin_api*)api;
|
||||||
|
struct codec_api* ci = (struct codec_api*)parm;
|
||||||
|
unsigned long samplerate,numbytes,totalsamples,samplesdone,nsamples;
|
||||||
|
int channels,bytespersample,bitspersample;
|
||||||
|
unsigned int i,j,n;
|
||||||
|
int endofstream;
|
||||||
|
|
||||||
|
/* Generic plugin initialisation */
|
||||||
|
TEST_PLUGIN_API(api);
|
||||||
|
|
||||||
|
/* if you are using a global api pointer, don't forget to copy it!
|
||||||
|
otherwise you will get lovely "I04: IllInstr" errors... :-) */
|
||||||
|
rb = api;
|
||||||
|
|
||||||
|
#ifndef SIMULATOR
|
||||||
|
rb->memcpy(iramstart, iramcopy, iramend-iramstart);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*10));
|
||||||
|
ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512));
|
||||||
|
|
||||||
|
next_track:
|
||||||
|
|
||||||
|
if (codec_init(api, ci)) {
|
||||||
|
return PLUGIN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIX: Correctly parse WAV header - we assume canonical 44-byte header */
|
||||||
|
|
||||||
|
n=(unsigned)(ci->read_filebuf(wavbuf,44));
|
||||||
|
if (n!=44) {
|
||||||
|
return PLUGIN_ERROR;
|
||||||
|
}
|
||||||
|
if ((memcmp(wavbuf,"RIFF",4)!=0) || (memcmp(&wavbuf[8],"WAVEfmt",7)!=0)) {
|
||||||
|
return PLUGIN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
samplerate=wavbuf[24]|(wavbuf[25]<<8)|(wavbuf[26]<<16)|(wavbuf[27]<<24);
|
||||||
|
bitspersample=wavbuf[34];
|
||||||
|
channels=wavbuf[22];
|
||||||
|
bytespersample=((bitspersample/8)*channels);
|
||||||
|
numbytes=(wavbuf[40]|(wavbuf[41]<<8)|(wavbuf[42]<<16)|(wavbuf[43]<<24));
|
||||||
|
totalsamples=numbytes/bytespersample;
|
||||||
|
|
||||||
|
if ((bitspersample!=16) || (channels != 2)) {
|
||||||
|
return PLUGIN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The main decoder loop */
|
||||||
|
|
||||||
|
samplesdone=0;
|
||||||
|
ci->set_elapsed(0);
|
||||||
|
endofstream=0;
|
||||||
|
while (!endofstream) {
|
||||||
|
rb->yield();
|
||||||
|
if (ci->stop_codec || ci->reload_codec) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
n=(unsigned)(ci->read_filebuf(wavbuf,sizeof(wavbuf)));
|
||||||
|
|
||||||
|
rb->yield();
|
||||||
|
|
||||||
|
if (n==0) break; /* End of stream */
|
||||||
|
|
||||||
|
nsamples=(n/bytespersample);
|
||||||
|
|
||||||
|
/* WAV files can contain extra data at the end - so we can't just
|
||||||
|
process until the end of the file */
|
||||||
|
|
||||||
|
if (samplesdone+nsamples > totalsamples) {
|
||||||
|
nsamples=(totalsamples-samplesdone);
|
||||||
|
n=nsamples*bytespersample;
|
||||||
|
endofstream=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Byte-swap data */
|
||||||
|
for (i=0;i<n;i+=2) {
|
||||||
|
j=wavbuf[i];
|
||||||
|
wavbuf[i]=wavbuf[i+1];
|
||||||
|
wavbuf[i+1]=j;
|
||||||
|
}
|
||||||
|
|
||||||
|
samplesdone+=nsamples;
|
||||||
|
ci->set_elapsed(samplesdone/(ci->id3->frequency/1000));
|
||||||
|
|
||||||
|
rb->yield();
|
||||||
|
while (!ci->audiobuffer_insert(wavbuf, n))
|
||||||
|
rb->yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ci->request_next_track())
|
||||||
|
goto next_track;
|
||||||
|
|
||||||
|
return PLUGIN_OK;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue