void writeSound(void) { int ret = soundBufferLen; //int i; while (mod.outMod->CanWrite() < ((ret*sndNumChannels*(sndBitsPerSample/8))<<(mod.dsp_isactive()?1:0))) Sleep(50); mod.SAAddPCMData((char *)soundFinalWave,sndNumChannels,sndBitsPerSample,decode_pos_ms); mod.VSAAddPCMData((char *)soundFinalWave,sndNumChannels,sndBitsPerSample,decode_pos_ms); decode_pos_ms += (ret/(2*sndNumChannels) * 1000) / (float)sndSamplesPerSec; if (mod.dsp_isactive()) ret=mod.dsp_dosamples((short *)soundFinalWave,ret/sndNumChannels/(sndBitsPerSample/8),sndBitsPerSample,sndNumChannels,sndSamplesPerSec)*(sndNumChannels*(sndBitsPerSample/8)); //if(soundFinalWave[0]==0&&soundFinalWave[1]==0&&soundFinalWave[2]==0&&soundFinalWave[3]==0) // DisplayError("%.2X%.2X%.2X%.2X - %d", soundFinalWave[0],soundFinalWave[1],soundFinalWave[2],soundFinalWave[3],ret); mod.outMod->Write((char *)&soundFinalWave,ret); if (seek_needed != -1) //if a seek is initiated { mod.outMod->Flush((long)decode_pos_ms); if (seek_needed < decode_pos_ms) //if we are asked to seek backwards. we have to start from the beginning { GSFClose(); GSFRun(lastfn); decode_pos_ms = 0; } } }
static int play(char *fn) { int song; int maxlatency; DWORD threadId; strcpy(current_filename_with_song, fn); song = extractSongNumber(fn, current_filename); if (!loadModule(current_filename, module, &module_len)) return -1; if (!ASAP_Load(&asap, current_filename, module, module_len)) return 1; if (song < 0) song = asap.module_info.default_song; duration = playSong(song); maxlatency = mod.outMod->Open(ASAP_SAMPLE_RATE, channels, BITS_PER_SAMPLE, -1, -1); if (maxlatency < 0) return 1; mod.SetInfo(BITS_PER_SAMPLE, ASAP_SAMPLE_RATE / 1000, channels, 1); mod.SAVSAInit(maxlatency, ASAP_SAMPLE_RATE); // the order of VSASetInfo's arguments in in2.h is wrong! // http://forums.winamp.com/showthread.php?postid=1841035 mod.VSASetInfo(ASAP_SAMPLE_RATE, channels); mod.outMod->SetVolume(-666); seek_needed = -1; thread_run = TRUE; thread_handle = CreateThread(NULL, 0, playThread, NULL, 0, &threadId); if (playing_info) updateInfoDialog(current_filename, song); return thread_handle != NULL ? 0 : 1; }
static void do_vis(char *data, int nch, int resolution, int position, unsigned samples) { static char vis_buffer[SAMPLES_PER_WRITE * FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS]; char *ptr; int size, count; /* * Winamp visuals may have problems accepting sample sizes larger than * 16 bits, so we reduce the sample size here if necessary. */ switch(resolution) { case 32: case 24: size = resolution / 8; count = samples * nch; data += size - 1; ptr = vis_buffer; while(count--) { *ptr++ = data[0] ^ 0x80; data += size; } data = vis_buffer; resolution = 8; /* fall through */ case 16: case 8: mod_.SAAddPCMData(data, nch, resolution, position); mod_.VSAAddPCMData(data, nch, resolution, position); } }
static int play(char *fn) { char filename[MAX_PATH]; int song; const ASAPInfo *info; int channels; int maxlatency; DWORD threadId; strcpy(playing_filename_with_song, fn); song = extractSongNumber(fn, filename); if (!loadModule(filename, module, &module_len)) return -1; if (!ASAP_Load(asap, filename, module, module_len)) return 1; info = ASAP_GetInfo(asap); if (song < 0) song = ASAPInfo_GetDefaultSong(info); duration = playSong(song); channels = ASAPInfo_GetChannels(info); maxlatency = mod.outMod->Open(ASAP_SAMPLE_RATE, channels, BITS_PER_SAMPLE, -1, -1); if (maxlatency < 0) return 1; mod.SetInfo(BITS_PER_SAMPLE, ASAP_SAMPLE_RATE / 1000, channels, 1); mod.SAVSAInit(maxlatency, ASAP_SAMPLE_RATE); // the order of VSASetInfo's arguments in in2.h is wrong! // http://forums.winamp.com/showthread.php?postid=1841035 mod.VSASetInfo(ASAP_SAMPLE_RATE, channels); mod.outMod->SetVolume(-666); seek_needed = -1; thread_run = TRUE; thread_handle = CreateThread(NULL, 0, playThread, NULL, 0, &threadId); setPlayingSong(filename, song); return thread_handle != NULL ? 0 : 1; }
static int play(char *fn) { LONGLONG filesize; DWORD thread_id; int maxlatency; /* checks */ if (decoder_ == 0) return 1; if (!(filesize = FileSize(fn))) return -1; /* init decoder */ if (!FLAC_plugin__decoder_init(decoder_, fn, filesize, &stream_data_, &flac_cfg.output)) return 1; strcpy(lastfn_, fn); /* open output */ maxlatency = mod_.outMod->Open(stream_data_.sample_rate, stream_data_.channels, stream_data_.output_bits_per_sample, -1, -1); if (maxlatency < 0) { FLAC_plugin__decoder_finish(decoder_); return 1; } /* set defaults */ mod_.outMod->SetVolume(-666); mod_.outMod->SetPan(0); /* initialize vis stuff */ mod_.SAVSAInit(maxlatency, stream_data_.sample_rate); mod_.VSASetInfo(stream_data_.sample_rate, stream_data_.channels); /* set info */ mod_.SetInfo(stream_data_.average_bps, stream_data_.sample_rate/1000, stream_data_.channels, 1); /* start playing thread */ paused = 0; thread_handle = CreateThread(NULL, 0, DecodeThread, NULL, 0, &thread_id); if (!thread_handle) return 1; return 0; }
int play(char *fn) { int maxlatency; int thread_id; if (InitADPFILE(fn, &cubefile) && InitADXFILE(fn, &cubefile) && InitDSPFILE(fn, &cubefile)) return 1; lstrcpy(lastfn,fn); paused=0; decode_pos_ms=0; seek_needed=-1; maxlatency = mod.outMod->Open(cubefile.ch[0].sample_rate,cubefile.NCH,BPS, -1,-1); if (maxlatency < 0) // error opening device { MessageBox(NULL, "error opening device", AppName, MB_OK); return 1; } // dividing by 1000 for the first parameter of setinfo makes it // display 'H'... for hundred.. i.e. 14H Kbps. mod.SetInfo((cubefile.ch[0].sample_rate*BPS*cubefile.NCH)/1000,cubefile.ch[0].sample_rate/1000,cubefile.NCH,1); // initialize vis stuff mod.SAVSAInit(maxlatency,cubefile.ch[0].sample_rate); mod.VSASetInfo(cubefile.NCH,cubefile.ch[0].sample_rate); mod.outMod->SetVolume(-666); // set the output plug-ins default volume killDecodeThread=0; thread_handle = (HANDLE) CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) DecodeThread,(void *) &killDecodeThread,0,&thread_id); SetThreadPriority(thread_handle,priarray[CPUPriority]); return 0; }
int play(char *fn) { int maxlatency; int thread_id; input_file = CreateFile(fn,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if (input_file == INVALID_HANDLE_VALUE) // error opening file { return 1; } file_length=GetFileSize(input_file,NULL); if(IsCurrentFile) { if(!strcmp(fn,lastfn)) { IsCurrentFile = TRUE; SongChanged=FALSE; } else { IsCurrentFile = FALSE; SongChanged=TRUE; } } strcpy(lastfn,fn); paused=0; decode_pos_ms=0; seek_needed=-1; GSFRun(fn); maxlatency = mod.outMod->Open(sndSamplesPerSec,sndNumChannels,sndBitsPerSample, -1,-1); if (maxlatency < 0) // error opening device { CloseHandle(input_file); input_file=INVALID_HANDLE_VALUE; return 1; } // dividing by 1000 for the first parameter of setinfo makes it // display 'H'... for hundred.. i.e. 14H Kbps. mod.SetInfo((sndSamplesPerSec*sndBitsPerSample*sndNumChannels)/1000,sndSamplesPerSec/1000,sndNumChannels,1); // initialize vis stuff mod.SAVSAInit(maxlatency,sndSamplesPerSec); mod.VSASetInfo(sndSamplesPerSec,sndNumChannels); mod.outMod->SetVolume(-666); // set the output plug-ins default volume killDecodeThread=0; thread_handle = (HANDLE) CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) DecodeThread,(void *) &killDecodeThread,0,&thread_id); return 0; }
DWORD WINAPI __stdcall DecodeThread(void *b) { int done=0; while (! *((int *)b) ) { if (seek_needed != -1) { //DisplayError("seek to %d",seek_needed); if (decode_pos_ms>seek_needed) { if (!InitADPFILE(NULL, &cubefile) || !InitADXFILE(NULL, &cubefile) || !InitDSPFILE(NULL, &cubefile)); decode_pos_ms=-1; // -1 ms, force it to work even if we want to seek to 0 } while (decode_pos_ms<seek_needed && ! *((int *)b)) { get_576_samples((short*)sample_buffer); mod.outMod->Flush((int)decode_pos_ms); decode_pos_ms+=(576.0*1000.0)/(double)cubefile.ch[0].sample_rate; } seek_needed=-1; } if (done) { mod.outMod->CanWrite(); if (!mod.outMod->IsPlaying()) { PostMessage(mod.hMainWindow,WM_WA_MPEG_EOF,0,0); return 0; } Sleep(10); } else if (mod.outMod->CanWrite() >= ((576*cubefile.NCH*(BPS/8))<<(mod.dsp_isactive()?1:0))) { int l=576*cubefile.NCH*(BPS/8); l=get_576_samples((short*)sample_buffer); if (!l) { done=1; } else { if (l==576*cubefile.NCH*(BPS/8)) { mod.SAAddPCMData((char *)sample_buffer,cubefile.NCH,BPS,mod.outMod->GetWrittenTime()); mod.VSAAddPCMData((char *)sample_buffer,cubefile.NCH,BPS,mod.outMod->GetWrittenTime()); } decode_pos_ms+=(576.0*1000.0)/(double)cubefile.ch[0].sample_rate; if (mod.dsp_isactive()) l=mod.dsp_dosamples((short *)sample_buffer,l/cubefile.NCH/(BPS/8),BPS,cubefile.NCH,cubefile.ch[0].sample_rate)*(cubefile.NCH*(BPS/8)); mod.outMod->Write(sample_buffer,l); } } else Sleep(20); } return 0; }
static DWORD WINAPI DecodeThread(void *unused) { const unsigned channels = stream_data_.channels; const unsigned bits_per_sample = stream_data_.bits_per_sample; const unsigned target_bps = stream_data_.output_bits_per_sample; const unsigned sample_rate = stream_data_.sample_rate; const unsigned fact = channels * (target_bps/8); while (stream_data_.is_playing) { /* seek needed */ if (stream_data_.seek_to != -1) { const int pos = FLAC_plugin__seek(decoder_, &stream_data_); if (pos != -1) mod_.outMod->Flush(pos); } /* stream ended */ else if (stream_data_.eof) { if (!mod_.outMod->IsPlaying()) { PostMessage(mod_.hMainWindow, WM_WA_MPEG_EOF, 0, 0); return 0; } Sleep(10); } /* decode */ else { /* decode samples */ int bytes = FLAC_plugin__decode(decoder_, &stream_data_, sample_buffer_); const int n = bytes / fact; /* visualization */ do_vis(sample_buffer_, channels, target_bps, mod_.outMod->GetWrittenTime(), n); /* dsp */ if (mod_.dsp_isactive()) bytes = mod_.dsp_dosamples((short*)sample_buffer_, n, target_bps, channels, sample_rate) * fact; /* output */ while (mod_.outMod->CanWrite()<bytes && stream_data_.is_playing && stream_data_.seek_to==-1) Sleep(20); if (stream_data_.is_playing && stream_data_.seek_to==-1) mod_.outMod->Write(sample_buffer_, bytes); /* show bitrate */ if (flac_cfg.display.show_bps) { const int rate = FLAC_plugin__get_rate(mod_.outMod->GetWrittenTime(), mod_.outMod->GetOutputTime(), &stream_data_); if (rate) mod_.SetInfo(rate/1000, stream_data_.sample_rate/1000, stream_data_.channels, 1); } } } return 0; }
int play(char *fn) { int maxlatency; int thread_id; HANDLE input_file = INVALID_HANDLE_VALUE; unsigned output_bits_per_sample; if(0 == decoder_) { return 1; } input_file = CreateFile(fn, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(input_file == INVALID_HANDLE_VALUE) { return -1; } CloseHandle(input_file); if(!safe_decoder_init_(fn, decoder_)) { return 1; } #ifdef FLAC__DO_DITHER output_bits_per_sample = min(file_info_.bits_per_sample, 16); #else output_bits_per_sample = file_info_.bits_per_sample; #endif strcpy(lastfn_, fn); paused_ = 0; decode_pos_ms_ = 0; seek_needed_ = -1; wide_samples_in_reservoir_ = 0; maxlatency = mod_.outMod->Open(file_info_.sample_rate, file_info_.channels, output_bits_per_sample, -1, -1); if(maxlatency < 0) { /* error opening device */ return 1; } /* dividing by 1000 for the first parameter of setinfo makes it */ /* display 'H'... for hundred.. i.e. 14H Kbps. */ mod_.SetInfo((file_info_.sample_rate*file_info_.bits_per_sample*file_info_.channels)/1000, file_info_.sample_rate/1000, file_info_.channels, 1); /* initialize vis stuff */ mod_.SAVSAInit(maxlatency, file_info_.sample_rate); mod_.VSASetInfo(file_info_.sample_rate, file_info_.channels); mod_.outMod->SetVolume(-666); /* set the output plug-ins default volume */ killDecodeThread = 0; thread_handle = (HANDLE) CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) DecodeThread, (void *) &killDecodeThread, 0, &thread_id); return 0; }
static DWORD WINAPI playThread(LPVOID dummy) { while (thread_run) { static #if BITS_PER_SAMPLE == 8 byte #else short #endif buffer[BUFFERED_BLOCKS * 2 #if SUPPORT_EQUALIZER * 2 #endif ]; int buffered_bytes = BUFFERED_BLOCKS * channels * (BITS_PER_SAMPLE / 8); if (seek_needed >= 0) { mod.outMod->Flush(seek_needed); ASAP_Seek(&asap, seek_needed); seek_needed = -1; } if (mod.outMod->CanWrite() >= buffered_bytes #if SUPPORT_EQUALIZER << mod.dsp_isactive() #endif ) { int t; buffered_bytes = ASAP_Generate(&asap, buffer, buffered_bytes, BITS_PER_SAMPLE); if (buffered_bytes <= 0) { mod.outMod->CanWrite(); if (!mod.outMod->IsPlaying()) { PostMessage(mod.hMainWindow, WM_WA_MPEG_EOF, 0, 0); return 0; } Sleep(10); continue; } t = mod.outMod->GetWrittenTime(); mod.SAAddPCMData(buffer, channels, BITS_PER_SAMPLE, t); mod.VSAAddPCMData(buffer, channels, BITS_PER_SAMPLE, t); #if SUPPORT_EQUALIZER t = buffered_bytes / (channels * (BITS_PER_SAMPLE / 8)); t = mod.dsp_dosamples((short *) buffer, t, BITS_PER_SAMPLE, channels, ASAP_SAMPLE_RATE); t *= channels * (BITS_PER_SAMPLE / 8); mod.outMod->Write((char *) buffer, t); #else mod.outMod->Write((char *) buffer, buffered_bytes); #endif } else Sleep(20); } return 0; }
void stop() { killPlayThread=1; if (play_thread_handle != INVALID_HANDLE_VALUE) { if (WaitForSingleObject(play_thread_handle, INFINITE) == WAIT_TIMEOUT) TerminateThread(play_thread_handle,0); CloseHandle(play_thread_handle); play_thread_handle = INVALID_HANDLE_VALUE; } faacDecClose(hDecoder); close_filestream(infile); mod.outMod->Close(); mod.SAVSADeInit(); if (memmap_buffer) LocalFree(memmap_buffer); if(seek_table) { free(seek_table); seek_table = NULL; seek_table_length = 0; } }
void stop() { if (thread_handle != INVALID_HANDLE_VALUE) { if (paused) unpause(); killDecodeThread=1; if (WaitForSingleObject(thread_handle,5000) == WAIT_TIMEOUT) { MessageBox(mod.hMainWindow,"error asking thread to die!\n","error killing decode thread",0); TerminateThread(thread_handle,0); } CloseHandle(thread_handle); thread_handle = INVALID_HANDLE_VALUE; } if (input_file != INVALID_HANDLE_VALUE) { CloseHandle(input_file); input_file=INVALID_HANDLE_VALUE; } GSFClose(); mod.outMod->Close(); mod.SAVSADeInit(); }
// stop playing. void stop() { if (thread_handle != INVALID_HANDLE_VALUE) { killDecodeThread=1; if (WaitForSingleObject(thread_handle,10000) == WAIT_TIMEOUT) { MessageBox(mod.hMainWindow,"error asking thread to die!\n", "error killing decode thread",0); TerminateThread(thread_handle,0); } CloseHandle(thread_handle); thread_handle = INVALID_HANDLE_VALUE; } // close output system mod.outMod->Close(); // deinitialize visualization mod.SAVSADeInit(); // CHANGEME! Write your own file closing code here if (input_file != INVALID_HANDLE_VALUE) { CloseHandle(input_file); input_file=INVALID_HANDLE_VALUE; } }
static void stop() { PostThreadMessage( self->PlayThreadID, WM_QUIT, 0, 0 ); WaitForSingleObject( self->PlayThread, INFINITE ); CloseHandle( self->PlayThread ); self->PlayThread = 0; self->PlayThreadID = 0; delete self->mod; self->mod = 0; inmod.outMod->Close(); inmod.SAVSADeInit(); }
static void stop(void) { if (thread_handle != NULL) { thread_run = FALSE; // wait max 10 seconds if (WaitForSingleObject(thread_handle, 10 * 1000) == WAIT_TIMEOUT) TerminateThread(thread_handle, 0); CloseHandle(thread_handle); thread_handle = NULL; } mod.outMod->Close(); mod.SAVSADeInit(); }
static int play( const in_char * fn ) { if ( !fn ) { return -1; } try { std::ifstream s( fn, std::ios::binary ); std::map< std::string, std::string > ctls; ctls["seek.sync_samples"] = "1"; self->mod = new openmpt::module( s, std::clog, ctls ); self->cached_filename = fn; self->cached_title = StringDecode( self->mod->get_metadata( "title" ), CP_UTF8 ); self->cached_length = static_cast<int>( self->mod->get_duration_seconds() * 1000.0 ); self->cached_infotext = generate_infotext( self->cached_filename, *self->mod ); apply_options(); self->samplerate = self->settings.samplerate; self->channels = self->settings.channels; int maxlatency = inmod.outMod->Open( self->samplerate, self->channels, BPS, -1, -1 ); std::ostringstream str; str << maxlatency; inmod.SetInfo( self->mod->get_num_channels(), self->samplerate/1000, self->channels, 1 ); inmod.SAVSAInit( maxlatency, self->samplerate ); inmod.VSASetInfo( self->channels, self->samplerate ); inmod.outMod->SetVolume( -666 ); inmod.outMod->SetPan( 0 ); self->paused = false; self->decode_position_frames = 0; self->PlayThread = CreateThread( NULL, 0, DecodeThread, NULL, 0, &self->PlayThreadID ); return 0; } catch ( ... ) { if ( self->mod ) { delete self->mod; self->mod = 0; } return -1; } }
void stop() { if(thread_handle != INVALID_HANDLE_VALUE) { killDecodeThread = 1; if(WaitForSingleObject(thread_handle, INFINITE) == WAIT_TIMEOUT) { MessageBox(mod_.hMainWindow, "error asking thread to die!\n", "error killing decode thread", 0); TerminateThread(thread_handle, 0); } CloseHandle(thread_handle); thread_handle = INVALID_HANDLE_VALUE; } safe_decoder_finish_(decoder_); mod_.outMod->Close(); mod_.SAVSADeInit(); }
static void stop() { if (thread_handle) { stream_data_.is_playing = false; if (WaitForSingleObject(thread_handle, 2000) == WAIT_TIMEOUT) { FLAC_plugin__show_error("Error while stopping decoding thread."); TerminateThread(thread_handle, 0); } CloseHandle(thread_handle); thread_handle = NULL; } FLAC_plugin__decoder_finish(decoder_); mod_.outMod->Close(); mod_.SAVSADeInit(); }
static DWORD WINAPI DecodeThread( LPVOID ) { MSG msg; PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ); bool eof = false; while ( true ) { bool quit = false; while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { if ( msg.message == WM_QUIT ) { quit = true; } else if ( msg.message == WM_OPENMPT_SEEK ) { double pos_seconds = self->mod->set_position_seconds( msg.lParam * 0.001 ); self->decode_position_frames = (std::int64_t)( pos_seconds * (double)self->samplerate); eof = false; inmod.outMod->Flush( (int)( pos_seconds * 1000.0 ) ); } } if ( quit ) { break; } if ( eof ) { inmod.outMod->CanWrite(); // update output plugin state if ( !inmod.outMod->IsPlaying() ) { PostMessage( inmod.hMainWindow, WM_WA_MPEG_EOF, 0, 0 ); return 0; } Sleep( 10 ); } else { bool dsp_active = inmod.dsp_isactive() ? true : false; if ( inmod.outMod->CanWrite() >= (int)( WINAMP_BUFFER_SIZE_FRAMES * self->channels * sizeof( signed short ) ) * ( dsp_active ? WINAMP_DSP_HEADROOM_FACTOR : 1 ) ) { int frames = 0; switch ( self->channels ) { case 1: frames = self->mod->read( self->samplerate, WINAMP_BUFFER_SIZE_FRAMES, (&(self->buffer[0]))+0*WINAMP_BUFFER_SIZE_FRAMES ); for ( int frame = 0; frame < frames; frame++ ) { self->interleaved_buffer[frame*1+0] = self->buffer[0*WINAMP_BUFFER_SIZE_FRAMES+frame]; } break; case 2: frames = self->mod->read( self->samplerate, WINAMP_BUFFER_SIZE_FRAMES, (&(self->buffer[0]))+0*WINAMP_BUFFER_SIZE_FRAMES, (&(self->buffer[0]))+1*WINAMP_BUFFER_SIZE_FRAMES ); for ( int frame = 0; frame < frames; frame++ ) { self->interleaved_buffer[frame*2+0] = self->buffer[0*WINAMP_BUFFER_SIZE_FRAMES+frame]; self->interleaved_buffer[frame*2+1] = self->buffer[1*WINAMP_BUFFER_SIZE_FRAMES+frame]; } break; case 4: frames = self->mod->read( self->samplerate, WINAMP_BUFFER_SIZE_FRAMES, (&(self->buffer[0]))+0*WINAMP_BUFFER_SIZE_FRAMES, (&(self->buffer[0]))+1*WINAMP_BUFFER_SIZE_FRAMES, (&(self->buffer[0]))+2*WINAMP_BUFFER_SIZE_FRAMES, (&(self->buffer[0]))+3*WINAMP_BUFFER_SIZE_FRAMES ); for ( int frame = 0; frame < frames; frame++ ) { self->interleaved_buffer[frame*4+0] = self->buffer[0*WINAMP_BUFFER_SIZE_FRAMES+frame]; self->interleaved_buffer[frame*4+1] = self->buffer[1*WINAMP_BUFFER_SIZE_FRAMES+frame]; self->interleaved_buffer[frame*4+2] = self->buffer[2*WINAMP_BUFFER_SIZE_FRAMES+frame]; self->interleaved_buffer[frame*4+3] = self->buffer[3*WINAMP_BUFFER_SIZE_FRAMES+frame]; } break; } if ( frames == 0 ) { eof = true; } else { self->decode_position_frames += frames; std::int64_t decode_pos_ms = (self->decode_position_frames * 1000 / self->samplerate ); inmod.SAAddPCMData( &( self->interleaved_buffer[0] ), self->channels, BPS, (int)decode_pos_ms ); inmod.VSAAddPCMData( &( self->interleaved_buffer[0] ), self->channels, BPS, (int)decode_pos_ms ); if ( dsp_active ) { frames = inmod.dsp_dosamples( &( self->interleaved_buffer[0] ), frames, BPS, self->channels, self->samplerate ); } int bytes = frames * self->channels * sizeof( signed short ); inmod.outMod->Write( (char*)&( self->interleaved_buffer[0] ), bytes ); } } else { Sleep( 10 ); } } } return 0; }
DWORD WINAPI __stdcall DecodeThread(void *b) { int done = 0; while(! *((int *)b) ) { const unsigned channels = file_info_.channels; const unsigned bits_per_sample = file_info_.bits_per_sample; #ifdef FLAC__DO_DITHER const unsigned target_bps = min(bits_per_sample, 16); #else const unsigned target_bps = bits_per_sample; #endif const unsigned sample_rate = file_info_.sample_rate; if(seek_needed_ != -1) { const double distance = (double)seek_needed_ / (double)getlength(); const unsigned target_sample = (unsigned)(distance * (double)file_info_.total_samples); if(FLAC__file_decoder_seek_absolute(decoder_, (FLAC__uint64)target_sample)) { decode_pos_ms_ = (int)(distance * (double)getlength()); seek_needed_ = -1; done = 0; mod_.outMod->Flush(decode_pos_ms_); } } if(done) { if(!mod_.outMod->IsPlaying()) { PostMessage(mod_.hMainWindow, WM_WA_MPEG_EOF, 0, 0); return 0; } Sleep(10); } else if(mod_.outMod->CanWrite() >= ((int)(SAMPLES_PER_WRITE*channels*((target_bps+7)/8)) << (mod_.dsp_isactive()?1:0))) { while(wide_samples_in_reservoir_ < SAMPLES_PER_WRITE) { if(FLAC__file_decoder_get_state(decoder_) == FLAC__FILE_DECODER_END_OF_FILE) { done = 1; break; } else if(!FLAC__file_decoder_process_single(decoder_)) { MessageBox(mod_.hMainWindow, FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder_)], "READ ERROR processing frame", 0); done = 1; break; } } if(wide_samples_in_reservoir_ == 0) { done = 1; } else { const unsigned n = min(wide_samples_in_reservoir_, SAMPLES_PER_WRITE); const unsigned delta = n * channels; int bytes = (int)FLAC__plugin_common__pack_pcm_signed_little_endian(sample_buffer_, reservoir_, n, channels, bits_per_sample, target_bps); unsigned i; for(i = delta; i < wide_samples_in_reservoir_ * channels; i++) reservoir_[i-delta] = reservoir_[i]; wide_samples_in_reservoir_ -= n; do_vis((char *)sample_buffer_, channels, target_bps, decode_pos_ms_, n); decode_pos_ms_ += (n*1000 + sample_rate/2)/sample_rate; if(mod_.dsp_isactive()) bytes = mod_.dsp_dosamples((short *)sample_buffer_, n, target_bps, channels, sample_rate) * (channels*target_bps/8); mod_.outMod->Write(sample_buffer_, bytes); } } else Sleep(20); } return 0; }
int play(char *fn) { int maxlatency; int thread_id; current_file_mode = m_memmap_file; if (current_file_mode) { if (play_memmap(fn)) return -1; } else { if (play_file(fn)) return -1; } if(seek_table) { free(seek_table); seek_table = NULL; seek_table_length = 0; } get_AAC_format(fn, &file_info, &seek_table, &seek_table_length, 0); if(infile->http) { /* No seeking in http streams */ mod.is_seekable = 0; } else { if (file_info.headertype == 2) /* ADTS header - seekable */ mod.is_seekable = 1; else mod.is_seekable = 0; /* ADIF or Headerless - not seekable */ } strcpy(lastfn,fn); paused=0; decode_pos_ms=0; seek_needed=-1; /* To RageAmp: This is really needed, because aacinfo isn't very accurate on ADIF files yet. Can be fixed though :-) */ file_info.sampling_rate = samplerate; file_info.channels = frameInfo.channels; maxlatency = mod.outMod->Open(file_info.sampling_rate, file_info.channels, 16, -1,-1); if (maxlatency < 0) // error opening device { return -1; } // initialize vis stuff mod.SAVSAInit(maxlatency, file_info.sampling_rate); mod.VSASetInfo(file_info.sampling_rate, file_info.channels); mod.SetInfo(file_info.bitrate/1000, file_info.sampling_rate/1000, file_info.channels,1); mod.outMod->SetVolume(-666); // set the output plug-ins default volume killPlayThread = 0; if((play_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) PlayThread, (void *) &killPlayThread, 0, &thread_id)) == NULL) { MessageBox(mod.hMainWindow, "Fatal error: Cannot create playback thread\n", "FAAD Error", MB_OK); return -1; } // Note: This line seriously slows down start up time if(m_priority != 3) // if the priority in config window is set to normal, there is nothing to reset! SetThreadPriority(play_thread_handle, priority_table[m_priority]); return 0; }
DWORD WINAPI DecodeThread(LPVOID b) { int done=0; // set to TRUE if decoding has finished while (!killDecodeThread) { if (seek_needed != -1) // seek is needed. { int offs; decode_pos_ms = seek_needed; seek_needed=-1; done=0; mod.outMod->Flush(decode_pos_ms); // flush output device and set // output position to the seek position offs = MulDiv(decode_pos_ms,SAMPLERATE,1000); // decode_pos_ms*SAMPLERATE/1000 SetFilePointer(input_file,offs*NCH*(BPS/8),NULL,FILE_BEGIN); // seek! } if (done) // done was set to TRUE during decoding, signaling eof { mod.outMod->CanWrite(); // some output drivers need CanWrite // to be called on a regular basis. if (!mod.outMod->IsPlaying()) { // we're done playing, so tell Winamp and quit the thread. PostMessage(mod.hMainWindow,WM_WA_MPEG_EOF,0,0); return 0; // quit thread } Sleep(10); // give a little CPU time back to the system. } else if (mod.outMod->CanWrite() >= ((576*NCH*(BPS/8))*(mod.dsp_isactive()?2:1))) // CanWrite() returns the number of bytes you can write, so we check that // to the block size. the reason we multiply the block size by two if // mod.dsp_isactive() is that DSP plug-ins can change it by up to a // factor of two (for tempo adjustment). { int l=576*NCH*(BPS/8); // block length in bytes static char sample_buffer[576*NCH*(BPS/8)*2]; // sample buffer. twice as // big as the blocksize l=get_576_samples(sample_buffer); // retrieve samples if (!l) // no samples means we're at eof { done=1; } else // we got samples! { // give the samples to the vis subsystems mod.SAAddPCMData((char *)sample_buffer,NCH,BPS,decode_pos_ms); mod.VSAAddPCMData((char *)sample_buffer,NCH,BPS,decode_pos_ms); // adjust decode position variable decode_pos_ms+=(576*1000)/SAMPLERATE; // if we have a DSP plug-in, then call it on our samples if (mod.dsp_isactive()) l=mod.dsp_dosamples( (short *)sample_buffer,l/NCH/(BPS/8),BPS,NCH,SAMPLERATE ) // dsp_dosamples *(NCH*(BPS/8)); // write the pcm data to the output system mod.outMod->Write(sample_buffer,l); } } else Sleep(20); // if we can't write data, wait a little bit. Otherwise, continue // through the loop writing more data (without sleeping) } return 0; }
DWORD WINAPI PlayThread(void *b) { int done=0; int l; int decoded_frames=0; int br_calc_frames=0; int br_bytes_consumed=0; unsigned long bytesconsumed; PlayThreadAlive = 1; last_frame = 0; while (! *((int *)b) ) { if (seek_needed != -1) { int seconds; // Round off to a second seconds = seek_needed - (seek_needed%1000); mod.outMod->Flush(decode_pos_ms); aac_seek(seconds, seek_table); decode_pos_ms = seconds; seek_needed = -1; decoded_frames = 0; br_calc_frames = 0; br_bytes_consumed = 0; } if (done) { mod.outMod->CanWrite(); if (!mod.outMod->IsPlaying()) { PostMessage(mod.hMainWindow,WM_WA_AAC_EOF,0,0); PlayThreadAlive = 0; return 0; } Sleep(10); } //assume that max channels is 2. else if (mod.outMod->CanWrite() >= ((1024*file_info.channels*sizeof(short))<<(mod.dsp_isactive()?1:0))) { if(last_frame) { done=1; } else { if (current_file_mode) bytesconsumed = PlayThread_memmap(); else bytesconsumed = PlayThread_file(); decoded_frames++; br_calc_frames++; br_bytes_consumed += bytesconsumed; /* Update the variable bitrate about every second */ if(m_variable_bitrate_display && br_calc_frames == 43) { int br; br = (int)((br_bytes_consumed * 8) / (decoded_frames / 43.07)); mod.SetInfo(br/1000, file_info.sampling_rate/1000, file_info.channels, 1); br_calc_frames = 0; } if (!killPlayThread && (frameInfo.samples > 0)) { mod.SAAddPCMData(sample_buffer,file_info.channels, 16, decode_pos_ms); mod.VSAAddPCMData(sample_buffer,file_info.channels, 16, decode_pos_ms); decode_pos_ms+=(1024*1000)/file_info.sampling_rate; if (mod.dsp_isactive()) l=mod.dsp_dosamples((short *)sample_buffer,frameInfo.samples*sizeof(short)/file_info.channels/(16/8),16,file_info.channels,file_info.sampling_rate)*(file_info.channels*(16/8)); else l = frameInfo.samples*sizeof(short); mod.outMod->Write(sample_buffer, l); } } } else { Sleep(10); } } if(seek_table) { free(seek_table); seek_table = NULL; seek_table_length = 0; } PlayThreadAlive = 0; return 0; }
// called when winamp wants to play a file int play(const char *fn) { int maxlatency; int thread_id; paused=0; decode_pos_ms=0; seek_needed=-1; // CHANGEME! Write your own file opening code here input_file = CreateFile(fn,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if (input_file == INVALID_HANDLE_VALUE) // error opening file { // we return error. 1 means to keep going in the playlist, -1 // means to stop the playlist. return 1; } file_length=GetFileSize(input_file,NULL); strcpy(lastfn,fn); // -1 and -1 are to specify buffer and prebuffer lengths. // -1 means to use the default, which all input plug-ins should // really do. maxlatency = mod.outMod->Open(SAMPLERATE,NCH,BPS, -1,-1); // maxlatency is the maxium latency between a outMod->Write() call and // when you hear those samples. In ms. Used primarily by the visualization // system. if (maxlatency < 0) // error opening device { CloseHandle(input_file); input_file=INVALID_HANDLE_VALUE; return 1; } // dividing by 1000 for the first parameter of setinfo makes it // display 'H'... for hundred.. i.e. 14H Kbps. mod.SetInfo((SAMPLERATE*BPS*NCH)/1000,SAMPLERATE/1000,NCH,1); // initialize visualization stuff mod.SAVSAInit(maxlatency,SAMPLERATE); mod.VSASetInfo(SAMPLERATE,NCH); // set the output plug-ins default volume. // volume is 0-255, -666 is a token for // current volume. mod.outMod->SetVolume(-666); // launch decode thread killDecodeThread=0; thread_handle = (HANDLE) CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) DecodeThread,NULL,0,&thread_id); return 0; }