/* WMA to WAV converter. * * Copyright (C) 2004, McMCC * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __WMA_2_WAV_C__ #define __WMA_2_WAV_C__ #include #include #include #include #include #include #include #include #ifdef HAVE_AV_CONFIG_H #undef HAVE_AV_CONFIG_H #endif #include "avformat.h" #include "avcodec.h" #define VER "0.1beta3" #define DATE "07-09-2004" #define COMMENT "WMA&OGG2WAV v." VER " converter from http://mcmcc.bat.ru" #define WRITE_U32(buf, x) *(buf) = (unsigned char)((x)&0xff);\ *((buf)+1) = (unsigned char)(((x)>>8)&0xff);\ *((buf)+2) = (unsigned char)(((x)>>16)&0xff);\ *((buf)+3) = (unsigned char)(((x)>>24)&0xff); #define WRITE_U16(buf, x) *(buf) = (unsigned char)((x)&0xff);\ *((buf)+1) = (unsigned char)(((x)>>8)&0xff); void ReportMemory(int id,const unsigned char *mem); static unsigned char headbuf[44]; static char *getlocale() { char *str = 0; char *langStr = getenv("LANG"); if (langStr) { str = strstr(langStr, "."); } if(str) *str++; else str = "US-ASCII"; return str; } static int last_char(char *str, int len) { int i; for(i=len-1; i >= 0; i--) { if(str[i] != ' ') { i++; break; } } if(i<0) i=0; return i; } static void tag_recode(char *before, char *codep, int len) { int result; iconv_t frt; char ansb[len]; char ansa[len]; char *ansbptr = ansb; char *ansaptr = ansa; int len1 = 2 * len; strncpy(ansb, before, len); frt = iconv_open(codep, getlocale()); if (frt == (iconv_t) - 1) return; result = iconv(frt, &ansbptr, &len, &ansaptr, &len1); if (result == (size_t) - 1) return; else { memset(before, 0, sizeof(before)); memcpy(before, ansa, last_char(ansa, sizeof(ansa))); } if (iconv_close(frt) != 0) if (iconv_close(frt) != 0) return; return; } static int write_prelim_header(AVCodecContext *c, FILE *out) { unsigned int size = 0x7fffffff; int bits = 16; int channels = c->channels; int samplerate = c->sample_rate; int bytespersec = channels*samplerate*bits/8; int align = channels*bits/8; int samplesize = bits; memcpy(headbuf, "RIFF", 4); WRITE_U32(headbuf+4, size-8); memcpy(headbuf+8, "WAVE", 4); memcpy(headbuf+12, "fmt ", 4); WRITE_U32(headbuf+16, 16); WRITE_U16(headbuf+20, 1); /* format */ WRITE_U16(headbuf+22, channels); WRITE_U32(headbuf+24, samplerate); WRITE_U32(headbuf+28, bytespersec); WRITE_U16(headbuf+32, align); WRITE_U16(headbuf+34, samplesize); memcpy(headbuf+36, "data", 4); WRITE_U32(headbuf+40, size - 44); if(fwrite(headbuf, 1, 44, out) != 44) { fprintf(stderr, "Error: Failed to write wav header: %s\n", strerror(errno)); return 1; } return 0; } static int rewrite_header(FILE *out, unsigned int written) { unsigned int length = written; length += 44; WRITE_U32(headbuf+4, length-8); WRITE_U32(headbuf+40, length-44); if(fseek(out, 0, SEEK_SET) != 0) return 1; if(fwrite(headbuf, 1, 44, out) != 44) { fprintf(stderr, "Error: Failed to write wav header: %s\n", strerror(errno)); return 1; } return 0; } static void audio_decode(const char *filename, const char *filenameout, char *codep, int set) { AVCodec *codec; AVPacket pkt; AVCodecContext *c= NULL; AVFormatContext *ic= NULL; int out_size, size, len, i, ret; int tns, thh, tmm, tss; uint8_t *outbuf = NULL; uint8_t *inbuf_ptr; FILE *outfile = NULL; extern AVInputFormat asf_demuxer; char tmp[24]; unsigned int written = 0; if((ret=av_open_input_file(&ic, filename, NULL, 0, NULL)) < 0) { printf("Error: could not open file %s with error %d!\n", filename, ret); exit(1); } printf("ret is %d\n", ret); for (i = 0; i < ic->nb_streams; i++) { c = &ic->streams[i]->codec; if(c->codec_type == CODEC_TYPE_AUDIO){ printf("found type\n"); break; } else printf("No audio found in stream %d\n", i); } av_find_stream_info(ic); printf("samplerate is %d\n", c->sample_rate); printf("codecid is %d\n",c->codec_id); codec = avcodec_find_decoder(c->codec_id); //codec=&wmav2_decoder; if (!codec) { fprintf(stderr, "Error: codec not found\n"); exit(1); } printf("i'm here\n"); /* open it */ if (avcodec_open(c, codec) < 0) { fprintf(stderr, "Error: could not open codec\n"); goto end; } printf("i'm here2\n"); if (filenameout) { outfile = fopen(filenameout, "w"); if (!outfile) { fprintf(stderr, "Error: not open to write output file\n"); goto end; } outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); } if(!set) { fprintf(stderr, "\n"); dump_format(ic, 0, filename, 0); if (ic->duration > 0) { tns = ic->duration/1000000LL; thh = tns/3600; tmm = (tns%3600)/60; tss = (tns%60); fprintf(stderr, "Time: %2d:%02d:%02d\n", thh, tmm, tss); } tns = 0; thh = 0; tmm = 0; tss = 0; fprintf(stderr, "\n"); } if (!filenameout) goto end; if (write_prelim_header(c, outfile)) { fprintf(stderr, "Error: not write WAV header in output file\n"); goto end; } int twink = 0; for(;;++twink) { if (av_read_frame(ic, &pkt) < 0) { break; } size = pkt.size; inbuf_ptr = pkt.data; tns = pkt.pts/1000000LL; thh = tns/3600; tmm = (tns%3600)/60; tss = (tns%60); if (tns) { /* fprintf(stderr, "SZ %d Decode Time: %2d:%02d:%02d bitrate: %d kb/s\r", size, thh, tmm, tss, c->bit_rate / 1000); */ } if (size == 0) { break; } while (size > 0) { len = avcodec_decode_audio(c, (short *)outbuf, &out_size, inbuf_ptr, size); ReportMemory(out_size,outbuf); if (len < 0) { break; } if (out_size <= 0) { continue; } if (out_size > 0) { if(fwrite(outbuf, 1, out_size, outfile) <= 0) { fprintf(stderr, "Error: not data write in output file\n"); goto end; } written += out_size; } size -= len; inbuf_ptr += len; } } fprintf(stderr, "\n"); if( rewrite_header(outfile, written)) { fprintf(stderr, "Error: not rewrite WAV header in output file\n"); goto end; } if(outfile) fclose(outfile); if(outbuf) free(outbuf); if(c) avcodec_close(c); if(ic) av_close_input_file(ic); return; end: if(outfile) fclose(outfile); if(outbuf) free(outbuf); if(c) avcodec_close(c); if(ic) av_close_input_file(ic); exit(1); } static int info_file(char *filename, char *exten) { char *ext; ext = strrchr(filename, '.'); if (ext) if (!strcasecmp(ext, exten)) return 1; return 0; } static char *mkpdir(char *stringp) { char *tt; char *r, *d, dir[256]; char *n = NULL; stringp[strlen(stringp)-4] = 0; r = strrchr(stringp, '/'); *r++; memset(dir, 0, 256); while((tt=strsep(&stringp, "/"))) { if((tt[0] != 0) && !(n=strstr(tt,r))) { strcat(dir, tt); strcat(dir, "/"); mkdir(dir, 0666); } } if(n) strcat(dir, n); d = dir; return d; } static void infover() { fprintf(stderr,"\nWMA&OGG to WAV converter v.%s %s.\n", VER, DATE); fprintf(stderr,"Copyright (C) 2004 McMCC (see 'COPYING').\n"); fprintf(stderr,"THIS SOFTWARE COMES WITH ABSOLUTELY NO WARRANTY! USE AT YOUR OWN RISK!\n"); } static void help(char *aa) { infover(); fprintf(stderr,"\nUse %s file.wma - info only\n", aa); fprintf(stderr,"Use %s [-n] file.wma file.wav - converting wma to wav\n", aa); fprintf(stderr,"Converting wma format over script to other format:\n"); fprintf(stderr,"Use %s [options] -r runscript file.wma file.out\nor\n", aa); fprintf(stderr,"Use %s [options] -e extention -r runscript file.wma\n", aa); fprintf(stderr,"Converting directories (include subdirectories) with wma's over\n" "script in directory with other format:\n"); fprintf(stderr,"Use %s [options] -d -e extention -r runscript dir_wma dir_out\nor\n", aa); fprintf(stderr,"Use %s [options] -d -e extention -r runscript dir_wma\n", aa); fprintf(stderr,"\nExamples:\n"); fprintf(stderr,"%s test.wma\n", aa); fprintf(stderr,"%s test.wma test.wav\n", aa); fprintf(stderr,"%s -d -e ogg -r ./oggscript test.wma test.ogg\nor\n", aa); fprintf(stderr,"%s -d -e ogg -r ./oggscript test.wma\n", aa); fprintf(stderr,"%s -n -t cp1251 -d -e mp3 -r ./mp3script /home/test/dir_wma /home/test/dir_out\nor\n", aa); fprintf(stderr,"cd /home/test/dir_out\n"); fprintf(stderr,"%s -n -t cp1251 -d -e mp3 -r ./mp3script /home/test/dir_wma\n", aa); fprintf(stderr,"\nOptions:\n"); fprintf(stderr,"\t-e Set extension.\n"); fprintf(stderr,"\t-t Set convert tag to codepage.\n"); fprintf(stderr,"\t-n No print tag info.\n\n"); exit(0); } int main(int argc, char **argv) { int c, i, items; char cpage[16] = "KOI-7"; char tmpname[128] = "XXXXXX"; char runscr[256]; char *in_dir = NULL; char *out_dir = NULL; char **playlist_array; //playlist_t *playlist = NULL; char outfile[256]; char outdir[256]; char ext[5]; char wavfile[256]; struct stat stat_s; int not_option = 1; int dir_option = 0; int dir_set = 0; int no_info = 0; int run_set = 0; int ext_set = 0; extern AVInputFormat asf_demuxer; if(not_option && argc == 1) help(argv[0]); avcodec_init(); avcodec_register_all(); av_register_all(); //av_register_asf(); //register_wma(); register_protocol(&file_protocol); //hope this works dsputil_static_init(); //probably useless for audio //register_avcodec(&wmav1_decoder); //register_avcodec(&wmav2_decoder); //av_register_all(); //av_register_input_format(&asf_demuxer); //av_register_input_format(&mp3_demuxer); //asf_init(); /* Just calls av_register_input_format(&asf_demuxer); */ /* file protocols */ // register_protocol(&file_protocol); //hope those worked /* if(not_option && (info_file(argv[1], ".wma") || info_file(argv[1], ".ogg")) && (stat(argv[1], &stat_s) == 0) && argc == 2) { printf("option 1\n"); audio_decode(argv[1], NULL, NULL, cpage, 0); exit(2); } */ //i think this is the one i actually care about //if((not_option || no_info) && (info_file(argv[argc-2], ".wma")) && // (stat(argv[argc-2], &stat_s) == 0) && info_file(argv[argc-1], ".wav")) //{ // printf("option 2\n"); audio_decode(argv[argc-2], argv[argc-1], cpage, no_info); exit(2); //} printf("OHSHIT\n"); } void ReportMemory(int id,const unsigned char *mem) { fprintf(stderr, "%d : %02x %02x %02x %02x %02x %02x %02x %02x\n",id, mem[0],mem[1],mem[2],mem[3],mem[4],mem[5],mem[6],mem[7]); } #endif