diff --git a/Makefile.linux b/Makefile.linux index c85abfa..6009a8e 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -29,6 +29,7 @@ ODIR=./build/$(HOST_ARCH) SDIR=./source _DEPS = all.h \ + file.h \ flac.h \ mp3.h \ opus.h \ @@ -37,7 +38,8 @@ _DEPS = all.h \ DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS)) -_OBJ = flac.o \ +_OBJ = file.o \ + flac.o \ mp3.o \ opus.o \ test.o \ diff --git a/source/error.h b/source/error.h index a7998f4..9499133 100644 --- a/source/error.h +++ b/source/error.h @@ -1,4 +1,6 @@ +#if defined __arm__ #include <3ds.h> +#endif /* Errors that can't be explained with errno */ #define NDSP_INIT_FAIL 1000 @@ -6,6 +8,8 @@ #define FILE_NOT_SUPPORTED 1002 #define UNSUPPORTED_CHANNELS 1003 +#if defined __arm__ + /** * Struct to help error handling across threads. */ @@ -28,3 +32,5 @@ struct errInfo_t * \param err Error number. */ char* ctrmus_strerror(int err); + +#endif diff --git a/source/file.c b/source/file.c new file mode 100644 index 0000000..f2443de --- /dev/null +++ b/source/file.c @@ -0,0 +1,111 @@ +#include +#include +#include + +#include "error.h" +#include "file.h" +#include "flac.h" +#include "mp3.h" +#include "opus.h" +#include "vorbis.h" +#include "wav.h" + +/** + * Obtain file type string from file_types enum. + * + * \param ft File type enum. + * \return String representation of enum. + */ +const char* fileToStr(enum file_types ft) +{ + static const char *file_types_str[] = { + "UNKNOWN", + "WAV", + "FLAC", + "VORBIS", + "OPUS", + "MP3" + }; + + return file_types_str[ft]; +} + +/** + * Obtains file type. + * + * \param file File location. + * \return file_types enum or 0 on error and errno set. + */ +enum file_types getFileType(const char *file) +{ + FILE* ftest = fopen(file, "rb"); + uint32_t fileSig; + enum file_types file_type = FILE_TYPE_ERROR; + + /* Failure opening file */ + if(ftest == NULL) + return -1; + + if(fread(&fileSig, 4, 1, ftest) == 0) + goto err; + + switch(fileSig) + { + // "RIFF" + case 0x46464952: + if(fseek(ftest, 4, SEEK_CUR) != 0) + break; + + // "WAVE" + // Check required as AVI file format also uses "RIFF". + if(fread(&fileSig, 4, 1, ftest) == 0) + break; + + if(fileSig != 0x45564157) + break; + + file_type = FILE_TYPE_WAV; + break; + + // "fLaC" + case 0x43614c66: + file_type = FILE_TYPE_FLAC; + break; + + // "OggS" + case 0x5367674F: + if(isOpus(file) == 0) + file_type = FILE_TYPE_OPUS; + else if(isFlac(file) == 0) + file_type = FILE_TYPE_FLAC; + else if(isVorbis(file) == 0) + file_type = FILE_TYPE_VORBIS; + else + errno = FILE_NOT_SUPPORTED; + + break; + + default: + /* + * MP3 without ID3 tag, ID3v1 tag is at the end of file, or MP3 + * with ID3 tag at the beginning of the file. + */ + if((fileSig << 16) == 0xFBFF0000 || + (fileSig << 16) == 0xFAFF0000 || + (fileSig << 8) == 0x33444900) + { + file_type = FILE_TYPE_MP3; + break; + } + + /* TODO: Add this again at some point */ + //printf("Unknown magic number: %#010x\n.", fileSig); + errno = FILE_NOT_SUPPORTED; + break; + } + +err: + fclose(ftest); + return file_type; +} + diff --git a/source/file.h b/source/file.h new file mode 100644 index 0000000..09122de --- /dev/null +++ b/source/file.h @@ -0,0 +1,25 @@ +enum file_types +{ + FILE_TYPE_ERROR = 0, + FILE_TYPE_WAV, + FILE_TYPE_FLAC, + FILE_TYPE_VORBIS, + FILE_TYPE_OPUS, + FILE_TYPE_MP3 +}; + +/** + * Obtain file type string from file_types enum. + * + * \param ft File type enum. + * \return String representation of enum. + */ +const char* fileToStr(enum file_types ft); + +/** + * Obtains file type. + * + * \param file File location. + * \return file_types enum or 0 on error and errno set. + */ +enum file_types getFileType(const char *file); diff --git a/source/main.c b/source/main.c index e0e7832..271b01b 100644 --- a/source/main.c +++ b/source/main.c @@ -17,6 +17,7 @@ #include "all.h" #include "error.h" +#include "file.h" #include "main.h" #include "playback.h" diff --git a/source/playback.c b/source/playback.c index 9941416..b9a25e4 100644 --- a/source/playback.c +++ b/source/playback.c @@ -5,6 +5,7 @@ #include "all.h" #include "error.h" +#include "file.h" #include "flac.h" #include "mp3.h" #include "opus.h" @@ -42,87 +43,6 @@ bool isPlaying(void) return !stop; } -/** - * Obtains file type. - * - * \param file File location. - * \return File type, else negative and errno set. - */ -int getFileType(const char *file) -{ - FILE* ftest = fopen(file, "rb"); - uint32_t fileSig; - enum file_types file_type = FILE_TYPE_ERROR; - - /* Failure opening file */ - if(ftest == NULL) - return -1; - - if(fread(&fileSig, 4, 1, ftest) == 0) - goto err; - - switch(fileSig) - { - // "RIFF" - case 0x46464952: - if(fseek(ftest, 4, SEEK_CUR) != 0) - break; - - // "WAVE" - // Check required as AVI file format also uses "RIFF". - if(fread(&fileSig, 4, 1, ftest) == 0) - break; - - if(fileSig != 0x45564157) - break; - - file_type = FILE_TYPE_WAV; - break; - - // "fLaC" - case 0x43614c66: - file_type = FILE_TYPE_FLAC; - break; - - // "OggS" - case 0x5367674F: - if(isOpus(file) == 0) - file_type = FILE_TYPE_OPUS; - else if(isFlac(file) == 0) - file_type = FILE_TYPE_FLAC; - else if(isVorbis(file) == 0) - file_type = FILE_TYPE_VORBIS; - else - { - errno = FILE_NOT_SUPPORTED; - } - - break; - - default: - /* - * MP3 without ID3 tag, ID3v1 tag is at the end of file, or MP3 - * with ID3 tag at the beginning of the file. - */ - if((fileSig << 16) == 0xFBFF0000 || - (fileSig << 16) == 0xFAFF0000 || - (fileSig << 8) == 0x33444900) - { - file_type = FILE_TYPE_MP3; - break; - } - - /* TODO: Add this again at some point */ - //printf("Unknown magic number: %#010x\n.", fileSig); - errno = FILE_NOT_SUPPORTED; - break; - } - -err: - fclose(ftest); - return file_type; -} - /** * Should only be called from a new thread only, and have only one playback * thread at time. This function has not been written for more than one diff --git a/source/playback.h b/source/playback.h index da94ac8..f536cef 100644 --- a/source/playback.h +++ b/source/playback.h @@ -6,16 +6,6 @@ /* Channel to play music on */ #define CHANNEL 0x08 -enum file_types -{ - FILE_TYPE_ERROR = -1, - FILE_TYPE_WAV, - FILE_TYPE_FLAC, - FILE_TYPE_VORBIS, - FILE_TYPE_OPUS, - FILE_TYPE_MP3 -}; - struct decoder_fn { int (* init)(const char* file); @@ -49,14 +39,6 @@ void stopPlayback(void); */ bool isPlaying(void); -/** - * Obtains file type. - * - * \param file File location. - * \return File type, else negative and errno set. - */ -int getFileType(const char *file); - /** * Should only be called from a new thread only, and have only one playback * thread at time. This function has not been written for more than one diff --git a/source/test.c b/source/test.c index 0463949..56fc0fa 100644 --- a/source/test.c +++ b/source/test.c @@ -1,21 +1,28 @@ #if defined __gnu_linux__ +#include #include #include +#include +#include "error.h" +#include "file.h" #include "flac.h" #include "mp3.h" #include "opus.h" #include "playback.h" #include "vorbis.h" #include "wav.h" -#include "playback.h" /** * Test the various decoder modules in ctrmus. */ int main(int argc, char *argv[]) { - struct decoder_fn decoder; + struct decoder_fn decoder; + enum file_types ft; + const char *file = argv[1]; + int16_t *buffer = NULL; + FILE *out; if(argc != 2) { @@ -23,8 +30,8 @@ int main(int argc, char *argv[]) printf("%s FILE\n", argv[0]); return 0; } -#if 0 - switch(getFileType(argv[1])) + + switch(ft = getFileType(file)) { case FILE_TYPE_WAV: setWav(&decoder); @@ -47,9 +54,40 @@ int main(int argc, char *argv[]) break; default: + puts("Unsupported file."); goto err; } -#endif + + printf("Type: %s\n", fileToStr(ft)); + + if((*decoder.init)(file) != 0) + { + puts("Unable to initialise decoder."); + goto err; + } + + if((*decoder.channels)() > 2 || (*decoder.channels)() < 1) + { + puts("Unable to obtain number of channels."); + goto err; + } + + out = fopen("out", "wb"); + buffer = malloc(decoder.buffSize * sizeof(int16_t)); + + while(true) + { + size_t read = (*decoder.decode)(&buffer[0]); + + if(read <= 0) + break; + + fwrite(buffer, read * sizeof(int16_t), 1, out); + } + + (*decoder.exit)(); + free(buffer); + fclose(out); return 0;