//The recording stuff runs in its own thread //this prevents dropouts in the recording, in case the //bandwidth is smaller than the selected streaming bitrate void* snd_rec_thread(void *data) { int rb_read_bytes; int ogg_header_written; int enc_bytes_read; char *enc_buf = (char*)malloc(rec_rb.size * sizeof(char)*10); char *audio_buf = (char*)malloc(rec_rb.size * sizeof(short)); ogg_header_written = 0; while(record) { pthread_cond_wait(&rec_cond, &rec_mut); rb_read_bytes = rb_read(&rec_rb, audio_buf); if(rb_read_bytes == 0) continue; #if HAVE_LIBLAME if(!strcmp(cfg.rec.codec, "mp3")) { enc_bytes_read = lame_enc_encode(&lame_rec, (short int*)audio_buf, enc_buf, rb_read_bytes/(2*cfg.rec.channel), rec_rb.size*10); bytes_written += fwrite(enc_buf, 1, enc_bytes_read, cfg.rec.fd); } #endif #if HAVE_LIBVORBIS if (!strcmp(cfg.rec.codec, "ogg")) { if(!ogg_header_written) { vorbis_enc_write_header(&vorbis_rec); ogg_header_written = 1; } enc_bytes_read = vorbis_enc_encode(&vorbis_rec, (short int*)audio_buf, enc_buf, rb_read_bytes/(2*cfg.rec.channel)); bytes_written += fwrite(enc_buf, 1, enc_bytes_read, cfg.rec.fd); } #endif if (!strcmp(cfg.rec.codec, "wav")) { //this permanently updates the filesize value in the WAV header //so we still have a valid WAV file in case of a crash wav_write_header(cfg.rec.fd, cfg.audio.channel, cfg.audio.samplerate, /*bps*/ 16); bytes_written += fwrite(audio_buf, sizeof(char), rb_read_bytes, cfg.rec.fd); } } fclose(cfg.rec.fd); free(enc_buf); free(audio_buf); return NULL; }
int wav_mix(char *in1, char *in2, char *out, int samplerate, int swap, int stereo) { FILE *f_in1 = NULL; FILE *f_in2 = NULL; FILE *f_out = NULL; char *bitstream_buf1 = NULL; char *bitstream_buf2 = NULL; char *p1; char *f1; char *p2; char *f2; short int zero = 0; long file_size1; long file_size2 = 0; /* combine two wavs */ f_in1 = fopen(in1, "r"); if(!f_in1) { syslog(LOG_ERR,"File [%s] cannot be opened for read.\n", in1); return 1; } if(in2 != NULL) { f_in2 = fopen(in2, "r"); if(!f_in2) { fclose(f_in1); syslog(LOG_ERR,"File [%s] cannot be opened for read.\n", in2); return 1; } } for(int passOpen = 0; passOpen < 2; passOpen++) { if(passOpen == 1) { char *pointToLastDirSeparator = strrchr(out, '/'); if(pointToLastDirSeparator) { *pointToLastDirSeparator = 0; mkdir_r(out, 0777); *pointToLastDirSeparator = '/'; } else { break; } } f_out = fopen(out, "w"); if(f_out) { break; } } if(!f_out) { if(f_in1 != NULL) fclose(f_in1); if(f_in2 != NULL) fclose(f_in2); syslog(LOG_ERR,"File [%s] cannot be opened for write.\n", out); return 1; } char f_out_buffer[32768]; setvbuf(f_out, f_out_buffer, _IOFBF, 32768); wav_write_header(f_out, samplerate, stereo); fseek(f_in1, 0, SEEK_END); file_size1 = ftell(f_in1); fseek(f_in1, 0, SEEK_SET); if(in2 != NULL) { fseek(f_in2, 0, SEEK_END); file_size2 = ftell(f_in2); fseek(f_in2, 0, SEEK_SET); } bitstream_buf1 = new FILE_LINE char[file_size1]; if(!bitstream_buf1) { if(f_in1 != NULL) fclose(f_in1); if(f_in2 != NULL) fclose(f_in2); if(f_out != NULL) fclose(f_out); syslog(LOG_ERR,"Cannot malloc bitsream_buf1[%ld]", file_size1); return 1; } if(in2 != NULL) { bitstream_buf2 = new FILE_LINE char[file_size2]; if(!bitstream_buf2) { fclose(f_in1); fclose(f_in2); fclose(f_out); delete [] bitstream_buf1; syslog(LOG_ERR,"Cannot malloc bitsream_buf2[%ld]", file_size1); return 1; } } fread(bitstream_buf1, file_size1, 1, f_in1); p1 = bitstream_buf1; f1 = bitstream_buf1 + file_size1; if(in2 != NULL) { fread(bitstream_buf2, file_size2, 1, f_in2); p2 = bitstream_buf2; f2 = bitstream_buf2 + file_size2; } else { p2 = f2 = 0; } while(p1 < f1 || p2 < f2 ) { if(p1 < f1 && p2 < f2) { if(stereo) { /* stereo */ if(swap) { fwrite(p2, 2, 1, f_out); fwrite(p1, 2, 1, f_out); } else { fwrite(p1, 2, 1, f_out); fwrite(p2, 2, 1, f_out); } } else { /* mono */ slinear_saturated_add((short int*)p1, (short int*)p2); fwrite(p1, 2, 1, f_out); } p1 += 2; p2 += 2; } else if ( p1 < f1 ) { if(swap) { if(stereo) { fwrite(&zero, 2, 1, f_out); } fwrite(p1, 2, 1, f_out); } else { fwrite(p1, 2, 1, f_out); if(stereo) { fwrite(&zero, 2, 1, f_out); } } p1 += 2; } else if ( p2 < f2 ) { if(swap) { fwrite(p2, 2, 1, f_out); if(stereo) { fwrite(&zero, 2, 1, f_out); } } else { if(stereo) { fwrite(&zero, 2, 1, f_out); } fwrite(p2, 2, 1, f_out); } p2 += 2; } } wav_update_header(f_out); if(bitstream_buf1) delete [] bitstream_buf1; if(bitstream_buf2) delete [] bitstream_buf2; fclose(f_out); fclose(f_in1); if(f_in2) fclose(f_in2); return 0; }
int AudioConvertFunc(const char *outfilename,int sample_rate,int channels,int sec,const char *inputfilename,HWND mParentHwnd,UINT mMsg) { AVCodec *aCodec =NULL; AVPacket *packet = NULL; AVFormatContext *pFormatCtx =NULL; AVCodecContext *aCodecCtx= NULL; ReSampleContext* ResampleCtx=NULL; AVFrame *decoded_frame = NULL; int datasize; //int tempcount = 0; //long total_out_size=0; int64_t total_in_convert_size = 0; int audioConvertProgress = 0; int tempAudioConvertProgress; unsigned int i; int len, ret, buffer_size, count, audio_stream_index = -1, totle_samplenum = 0; FILE *outfile = NULL;// *infile; head_pama pt; int16_t *audio_buffer = NULL; int16_t *resamplebuff = NULL; int ResampleChange=0; int ChannelsChange=0; int tempret; packet = (AVPacket*)malloc(sizeof(AVPacket)); if (packet==NULL) { PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)(-1)); return -1; } packet->data=NULL; buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE * 100; audio_buffer = (int16_t *)av_malloc(buffer_size); if (audio_buffer==NULL) { if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)(-2)); return -2; } av_register_all(); av_init_packet(packet); #if 0 /**********尝试分解av_open_input_file函数*************/ int ret = 0; AVFormatParameters ap = { 0 }; AVDictionary *tmp = NULL; AVInputFormat *fmt = NULL; AVDictionary **options = NULL; if (!pFormatCtx && !(pFormatCtx = avformat_alloc_context())) return AVERROR(ENOMEM); if (fmt) pFormatCtx->iformat = fmt; if (options) av_dict_copy(&tmp, *options, 0); if ((ret = av_opt_set_dict(pFormatCtx, &tmp)) < 0) goto fail; AVDictionary *tmp = NULL; if (!pFormatCtx && !(pFormatCtx = avformat_alloc_context())) return AVERROR(ENOMEM); int ret; AVProbeData pd = {inputfilename, NULL, 0}; if (pFormatCtx->pb) { pFormatCtx->flags |= AVFMT_FLAG_CUSTOM_IO; if (!pFormatCtx->iformat) return av_probe_input_buffer(pFormatCtx->pb, &pFormatCtx->iformat, inputfilename, pFormatCtx, 0, 0); else if (pFormatCtx->iformat->flags & AVFMT_NOFILE) av_log(pFormatCtx, AV_LOG_WARNING, "Custom AVIOContext makes no sense and " "will be ignored with AVFMT_NOFILE format.\n"); return 0; } if ( (pFormatCtx->iformat && pFormatCtx->iformat->flags & AVFMT_NOFILE) || (!pFormatCtx->iformat && (pFormatCtx->iformat = av_probe_input_format(&pd, 0)))) return 0; URLContext *h; int err; err = ffurl_open(&h, inputfilename, AVIO_RDONLY); if (err < 0) return err; err = ffio_fdopen(pFormatCtx, h); if (err < 0) { ffurl_close(h); return err; } if (pFormatCtx->iformat) return 0; av_probe_input_buffer(pFormatCtx->pb, &pFormatCtx->iformat, inputfilename, pFormatCtx, 0, 0); if (pFormatCtx->iformat->flags & AVFMT_NEEDNUMBER) { if (!av_filename_number_test(inputfilename)) { ret = AVERROR(EINVAL); goto fail; } } pFormatCtx->duration = pFormatCtx->start_time = AV_NOPTS_VALUE; av_strlcpy(pFormatCtx->filename, inputfilename ? inputfilename : "", sizeof(pFormatCtx->filename)); /* allocate private data */ if (pFormatCtx->iformat->priv_data_size > 0) { if (!(pFormatCtx->priv_data = av_mallocz(pFormatCtx->iformat->priv_data_size))) { ret = AVERROR(ENOMEM); goto fail; } if (pFormatCtx->iformat->priv_class) { *(const AVClass**)pFormatCtx->priv_data = pFormatCtx->iformat->priv_class; av_opt_set_defaults(pFormatCtx->priv_data); if ((ret = av_opt_set_dict(pFormatCtx->priv_data, &tmp)) < 0) goto fail; } } /* e.g. AVFMT_NOFILE formats will not have a AVIOContext */ if (pFormatCtx->pb) ff_id3v2_read(pFormatCtx, ID3v2_DEFAULT_MAGIC); if (!(pFormatCtx->flags&AVFMT_FLAG_PRIV_OPT) && pFormatCtx->iformat->read_header) if ((ret = pFormatCtx->iformat->read_header(pFormatCtx, &ap)) < 0) goto fail; if (!(pFormatCtx->flags&AVFMT_FLAG_PRIV_OPT) && pFormatCtx->pb && !pFormatCtx->data_offset) pFormatCtx->data_offset = avio_tell(pFormatCtx->pb); pFormatCtx->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; if (options) { av_dict_free(options); *options = tmp; } return 0; fail: av_dict_free(&tmp); if (pFormatCtx->pb && !(pFormatCtx->flags & AVFMT_FLAG_CUSTOM_IO)) avio_close(pFormatCtx->pb); avformat_free_context(pFormatCtx); pFormatCtx = NULL; return ret; return err; /**********尝试分解av_open_input_file函数*************/ //pFormatCtx = avformat_alloc_context(); #endif ret = av_open_input_file(&pFormatCtx, inputfilename, NULL,0, NULL); if(ret < 0) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)1); return 1; } ret = av_find_stream_info(pFormatCtx); if( ret < 0) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)2); return 2; } audio_stream_index=-1; for(i=0; i< (signed)pFormatCtx->nb_streams; i++) { if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && audio_stream_index < 0) { audio_stream_index = i; break; } } if(audio_stream_index == -1) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)3); return 3; } aCodecCtx = pFormatCtx->streams[audio_stream_index]->codec; if (aCodecCtx==NULL) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)4); return 4; } aCodec = avcodec_find_decoder(aCodecCtx->codec_id); if(!aCodec) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } /*if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; }*/ PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)5); return 5; } //resample init if (channels==0) { channels=aCodecCtx->channels; } if (sample_rate==0) { sample_rate=aCodecCtx->sample_rate; } //if (aCodecCtx->channels!=channels) //{ // ChannelsChange=1; // ResampleChange=1; //} if (aCodecCtx->sample_rate!=sample_rate||aCodecCtx->channels!=channels) { ResampleChange=1; } if (ResampleChange==1) { ResampleCtx = av_audio_resample_init(channels,aCodecCtx->channels,sample_rate,aCodecCtx->sample_rate,SAMPLE_FMT_S16,SAMPLE_FMT_S16,16,10,0,1.0); if (ResampleCtx==NULL) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } /*if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; }*/ ResampleChange=0; PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)6); return 6; } resamplebuff=(int16_t *)malloc(buffer_size); if (resamplebuff==NULL) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } /*if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; }*/ if (ResampleChange==1&&ResampleCtx!=NULL) { audio_resample_close(ResampleCtx); ResampleCtx=NULL; } PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)7); return 7; } } // datasize=sec*sample_rate; if(avcodec_open(aCodecCtx, aCodec)<0) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; } if (ResampleChange==1&&ResampleCtx!=NULL&&resamplebuff!=NULL) { audio_resample_close(ResampleCtx); ResampleCtx=NULL; free(resamplebuff); resamplebuff=NULL; } ResampleChange=0; PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)8); return 8; } pt.bits = 16; pt.channels = channels; pt.rate = sample_rate; outfile = fopen(outfilename, "wb"); if (!outfile) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; } if (ResampleChange==1&&ResampleCtx!=NULL&&resamplebuff!=NULL) { audio_resample_close(ResampleCtx); ResampleCtx=NULL; free(resamplebuff); resamplebuff=NULL; } ResampleChange=0; PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)9); return 9; } fseek(outfile,44,SEEK_SET); while(av_read_frame(pFormatCtx, packet) >= 0) { CheckMessageQueue(); if(packet->stream_index == audio_stream_index) { //while(packet->size > 0) //{ buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE * 100; len = avcodec_decode_audio3(aCodecCtx, audio_buffer, &buffer_size, packet); if (len < 0) { break; } if(buffer_size > 0) { //resample if (ResampleChange==1) { int samples=buffer_size/ ((aCodecCtx->channels) * 2); int resamplenum= 0; resamplenum = audio_resample(ResampleCtx, resamplebuff, audio_buffer, samples); count = fwrite(resamplebuff, 2*channels, resamplenum, outfile); } else { count = fwrite(audio_buffer, 2*aCodecCtx->channels, buffer_size/((aCodecCtx->channels)*2), outfile); } totle_samplenum += count; } //tempcount++; //total_out_size += count*2*aCodecCtx->channels; total_in_convert_size += packet->size; tempAudioConvertProgress = 100*total_in_convert_size/(pFormatCtx->file_size); if(tempAudioConvertProgress != audioConvertProgress) { if(tempAudioConvertProgress == 100) tempAudioConvertProgress = 99; audioConvertProgress = tempAudioConvertProgress; tempret = PostMessage(mParentHwnd,mMsg,DECING_TAG,audioConvertProgress); } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } //packet->size -= len; //packet->data += len; //} if (datasize!=0&&totle_samplenum>=datasize) { break; } } } audioConvertProgress = 100; PostMessage(mParentHwnd,mMsg,DECING_TAG,audioConvertProgress); fseek(outfile,0,SEEK_SET); wav_write_header(outfile, pt, totle_samplenum); if (outfile!=NULL) { fclose(outfile); outfile=NULL; } if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; } if (packet!=NULL) { free(packet);// packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } if (ResampleChange==1) { if (resamplebuff!=NULL) { free(resamplebuff); resamplebuff=NULL; } if (ResampleCtx!=NULL) { audio_resample_close(ResampleCtx); ResampleCtx=NULL; } } if (totle_samplenum<=sample_rate*5) { PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)10); return 10; } PostMessage(mParentHwnd,mMsg,FINISH_TAG,NULL); return 0; }
int main(int argc, char **argv) { struct tap tapfile; struct wav wavfile; FILE *infile; long pulse; long i; fixedpoint len, accum; long channels[2]; int wave[2]; int sample; getopts(argc, argv); if (invert) { wave[0] = LOW; wave[1] = HIGH; } else { wave[0] = HIGH; wave[1] = LOW; } if (optind == argc) { infile = stdin; } else if (optind == argc - 1) { if (!strcmp(argv[optind], "-")) { infile = stdin; } else { infile = fopen(argv[optind], "rb"); if (!infile) { perror(argv[optind]); return 1; } } } else { fprintf(stderr, "%s: too many arguments\n", argv0); usage(); return 1; } if (tap_read_header(&tapfile, infile)) { fprintf(stderr, "%s: error reading TAP file\n", argv0); return 1; } wavfile.SampleRate = samplerate; wavfile.BitsPerSample = 8; wavfile.NumChannels = 1; if (wav_write_header(&wavfile, stdout)) { fprintf(stderr, "%s: error writing WAV file\n", argv0); return 1; } filter_init(&lowpass_filter, lowpass_freq, wavfile.SampleRate); #if 0 /* put one initial sample so the first pulse is recognized */ channels[0] = wave[1]; wav_put_sample(&wavfile, channels); accum = TO_FIXED(1.5); #else accum = TO_FIXED(2); #endif while ((pulse = tap_get_pulse(&tapfile)) >= 0) { //fprintf(stderr, "pulse: %6ld (%04lx)\n", pulse, pulse); //if (pulse < 8*256) //++pulsehist[pulse/8]; len = TO_FIXED(((double)pulse * samplerate / PAL_MHZ / speed / 1000000)); if (len < TO_FIXED(2)) { fprintf(stderr, "%s: warning: pulse length (%ld) is less than 2 samples\n", argv0, pulse); } #if 0 accum = FIXED_F(len + accum); #else len += accum; accum = FIXED_F(len); #endif #if 0 fprintf(stderr, "%ld.%03ld 0.%03ld \n", FIXED_I(len), FIXED_F(len) * 1000 / FIXED_ONE, FIXED_F(accum) * 1000 / FIXED_ONE); #endif for (i = 0; i < FIXED_I(len) / 2 - 1; ++i) { channels[0] = filter_lowpass(&lowpass_filter, wave[0]) << 16; wav_put_sample(&wavfile, channels); } for (; i < FIXED_I(len) - 2; ++i) { channels[0] = filter_lowpass(&lowpass_filter, wave[1]) << 16; wav_put_sample(&wavfile, channels); } #if 0 channels[0] = FIXED_MUL(wave[1], accum) + FIXED_MUL(wave[0], FIXED_ONE - accum); wav_put_sample(&wavfile, channels); #else sample = FIXED_MUL(wave[1], accum); channels[0] = filter_lowpass(&lowpass_filter, sample) << 16; wav_put_sample(&wavfile, channels); sample -= wave[1]; channels[0] = filter_lowpass(&lowpass_filter, sample) << 16; wav_put_sample(&wavfile, channels); #endif } wav_close(&wavfile); return 0; }
//The recording stuff runs in its own thread //this prevents dropouts in the recording in case the //bandwidth is smaller than the selected streaming bitrate void* snd_rec_thread(void *data) { int rb_bytes_read; int bytes_to_read; int ogg_header_written; int opus_header_written; int enc_bytes_read; char *enc_buf = (char*)malloc(rec_rb.size * sizeof(char)*10); char *audio_buf = (char*)malloc(rec_rb.size * sizeof(char)*10); ogg_header_written = 0; opus_header_written = 0; while(record) { pthread_cond_wait(&rec_cond, &rec_mut); if(next_file == 1) { if(!strcmp(cfg.rec.codec, "flac")) // The flac encoder closes the file flac_enc_close(&flac_rec); else fclose(cfg.rec.fd); cfg.rec.fd = next_fd; next_file = 0; if(!strcmp(cfg.rec.codec, "ogg")) { vorbis_enc_reinit(&vorbis_rec); ogg_header_written = 0; } if(!strcmp(cfg.rec.codec, "opus")) { opus_enc_reinit(&opus_rec); opus_header_written = 0; } if(!strcmp(cfg.rec.codec, "flac")) { flac_enc_reinit(&flac_rec); flac_enc_init_FILE(&flac_rec, cfg.rec.fd); } } // Opus needs a special treatment // The encoder needs a predefined count of frames // Therefore we don't feed the encoder with all data we have in the // ringbuffer at once if(!strcmp(cfg.rec.codec, "opus")) { bytes_to_read = 960 * sizeof(short)*cfg.audio.channel; while ((rb_filled(&rec_rb)) >= bytes_to_read) { rb_read_len(&rec_rb, audio_buf, bytes_to_read); if(!opus_header_written) { opus_enc_write_header(&opus_rec); opus_header_written = 1; } enc_bytes_read = opus_enc_encode(&opus_rec, (short*)audio_buf, enc_buf, bytes_to_read/(2*cfg.audio.channel)); kbytes_written += fwrite(enc_buf, 1, enc_bytes_read, cfg.rec.fd)/1024.0; } } else { if(rb_filled(&rec_rb) < framepacket_size*sizeof(short)) continue; rb_bytes_read = rb_read(&rec_rb, audio_buf); if(rb_bytes_read == 0) continue; if(!strcmp(cfg.rec.codec, "mp3")) { enc_bytes_read = lame_enc_encode(&lame_rec, (short*)audio_buf, enc_buf, rb_bytes_read/(2*cfg.audio.channel), rec_rb.size*10); kbytes_written += fwrite(enc_buf, 1, enc_bytes_read, cfg.rec.fd)/1024.0; } if(!strcmp(cfg.rec.codec, "ogg")) { if(!ogg_header_written) { vorbis_enc_write_header(&vorbis_rec); ogg_header_written = 1; } enc_bytes_read = vorbis_enc_encode(&vorbis_rec, (short*)audio_buf, enc_buf, rb_bytes_read/(2*cfg.audio.channel)); kbytes_written += fwrite(enc_buf, 1, enc_bytes_read, cfg.rec.fd)/1024.0; } if(!strcmp(cfg.rec.codec, "flac")) { flac_enc_encode(&flac_rec, (short*)audio_buf, rb_bytes_read/sizeof(short)/cfg.audio.channel, cfg.audio.channel); kbytes_written = flac_enc_get_bytes_written()/1024.0; } if(!strcmp(cfg.rec.codec, "wav")) { //this permanently updates the filesize value in the WAV header //so we still have a valid WAV file in case of a crash wav_write_header(cfg.rec.fd, cfg.audio.channel, cfg.audio.samplerate, 16); kbytes_written += fwrite(audio_buf, sizeof(char), rb_bytes_read, cfg.rec.fd)/1024.0; } if(!strcmp(cfg.rec.codec, "aac")) { enc_bytes_read = aac_enc_encode(&aac_rec, (short*) audio_buf, enc_buf, rb_bytes_read / (2*cfg.audio.channel), cfg.audio.channel); kbytes_written += fwrite(enc_buf, 1, enc_bytes_read, cfg.rec.fd) / 1024.0; } } } if(!strcmp(cfg.rec.codec, "flac")) // The flac encoder closes the file flac_enc_close(&flac_rec); else fclose(cfg.rec.fd); free(enc_buf); free(audio_buf); return NULL; }
void extract_wavs_from_drm(char * name) { FILE * drmfile; FILE * wavfile; size_t len; unsigned int version; unsigned int count; char * destdir = create_output_dir(name); if (!destdir) { fprintf(stderr, "Error creating output directory for file %s.\n", name); return; } if (fopen_s(&drmfile, name, "rb")) { fprintf(stderr, "Error opening file %s.\n", name); free(destdir); return; } len = fread(&version, sizeof(version), 1, drmfile); if (len != 1) goto read_err; if (version != 14) { fprintf(stderr, "DRM version 0x%02x is not supported.\n", version); goto bail; } len = fread(&count, sizeof(count), 1, drmfile); if (len != 1) goto read_err; struct ste * section_table = calloc(count, sizeof(struct ste)); if (!section_table) { fprintf(stderr, "Error allocating section table.\n"); goto bail; } len = fread((void *)section_table, sizeof(struct ste), count, drmfile); if (len != count) goto read_err; for (unsigned int i = 0; i < count; i++) { if (section_table[i].type != audio) { fseek(drmfile, (section_table[i].hdrlen * 8) + section_table[i].datalen, SEEK_CUR); continue; } char wavname[1024] = {0}; if (_snprintf_s(wavname, 1024, _TRUNCATE, "%s/%u.wav", destdir, section_table[i].id) == -1) { fprintf(stderr, "Error printing wav file name.\n"); goto bail; } if (fopen_s(&wavfile, wavname, "wb")) { fprintf(stderr, "Error creating wav file %s.\n", wavname); goto bail; } /* Leave space for the WAV header */ wav_skip_header(wavfile); /* Prepare DRM file */ fseek(drmfile, (section_table[i].hdrlen * 8), SEEK_CUR); unsigned int freq; len = fread(&freq, sizeof(freq), 1, drmfile); if (len != 1) goto read_err; /* Skip over loop points */ fseek(drmfile, 8, SEEK_CUR); if (xcs(drmfile, wavfile, section_table[i].datalen - 12) < 0) fprintf(stderr, "Error converting audio section %d.\n", i); /* Write WAV header */ unsigned int extract_size = ((section_table[i].datalen - 12) / 36) * 128; wav_write_header(wavfile, extract_size, 1, freq, 16); fclose(wavfile); } bail: free(destdir); fclose(drmfile); return; read_err: fprintf(stderr, "Read error in file %s.\n", name); free(destdir); fclose(drmfile); return; }