⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qcdfaad.c

📁 BHE的解码程序
💻 C
📖 第 1 页 / 共 2 页
字号:
}

unsigned long samplerate, channels;

int play_memmap(char *fn)
{
    int tagsize = 0;

    infile = open_filestream(fn);
    
	if (infile == NULL)
        return 1;

    fileread = filelength_filestream(infile);

    memmap_buffer = (char*)LocalAlloc(LPTR, fileread);
    read_buffer_filestream(infile, memmap_buffer, fileread);

    /* skip id3v2 tag */
    memmap_index = id3v2_tag(memmap_buffer);

    hDecoder = faacDecOpen();

	/* Copy the configuration dialog setting and use it as the default */
	/* initialize the decoder, and get samplerate and channel info */

    if( (buffercount = faacDecInit(hDecoder, memmap_buffer + memmap_index,
        fileread - memmap_index - 1, &samplerate, &channels)) < 0 )
    {
		show_error("Error opening input file");
		return 1;
    }

    memmap_index += buffercount;

    PlayThread_memmap();

    return 0;
}

int play_file(char *fn)
{
    int k;
    int tagsize;

    ZeroMemory(buffer, 768*2);

     infile = open_filestream(fn);
    
	if (infile == NULL)
        return 1;

	fileread = filelength_filestream(infile);

    buffercount = bytecount = 0;
    read_buffer_filestream(infile, buffer, 768*2);

    tagsize = id3v2_tag(buffer);

	/* If we find a tag, run right over it */
    if(tagsize)
	{
        if(infile->http)
        {
            int i;
            /* Crude way of doing this, but I believe its fast enough to not make a big difference */
            close_filestream(infile);
            infile = open_filestream(fn);

            for(i=0; i < tagsize; i++)
                read_byte_filestream(infile);
        }
        else
            seek_filestream(infile, tagsize, FILE_BEGIN);

        bytecount = tagsize;
        buffercount = 0;
        read_buffer_filestream(infile, buffer, 768*2);
    }

    hDecoder = faacDecOpen();

	/* Copy the configuration dialog setting and use it as the default */
	/* initialize the decoder, and get samplerate and channel info */

    if((buffercount = faacDecInit(hDecoder, buffer, 768*2, &samplerate, &channels)) < 0)
    {
		show_error("Error opening input file");
		return 1;
    }

    if(buffercount > 0)
	{
		bytecount += buffercount;

		for (k = 0; k < (768*2 - buffercount); k++)
			buffer[k] = buffer[k + buffercount];

		read_buffer_filestream(infile, buffer + (768*2) - buffercount, buffercount);
		buffercount = 0;
	}

    PlayThread_file();

    return 0;
}


//-----------------------------------------------------------------------------

BOOL Play(LPCSTR medianame, int playfrom, int playto, int flags)
{
	if(stricmp(lastfn, medianame) != 0)
	{
		sQCDCallbacks.toPlayer.OutputStop(STOPFLAG_PLAYDONE);
		Stop(lastfn, STOPFLAG_PLAYDONE);
	}

	if(paused)
	{
		// Update the player controls to reflect the new unpaused state
		sQCDCallbacks.toPlayer.OutputPause(0);

		Pause(medianame, PAUSE_DISABLED);

		if (playfrom >= 0)
			seek_needed = playfrom;
	}
	else if(play_thread_handle != INVALID_HANDLE_VALUE)
	{
		seek_needed = playfrom;
		return TRUE;
	}
	else
	{
		int thread_id;

		// alloc the input buffer
		buffer = (unsigned char*)LocalAlloc(LPTR, 768*2);

		current_file_mode = m_memmap_file;
		
		if(current_file_mode)
		{
			if(play_memmap((char *)medianame))
				return FALSE;
		}
		else
		{
			if(play_file((char *)medianame))
				return FALSE;
		}
		
		if(seek_table)
		{
			free(seek_table);
			seek_table = NULL;
			seek_table_length = 0;
		}
		
		get_AAC_format((char *)medianame, &file_info, &seek_table, &seek_table_length, 0);
		
		seek_needed = playfrom > 0 ? playfrom : -1;
		killPlayThread = 0;
		strcpy(lastfn,medianame);

		/*
		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;

		play_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) PlayThread, (void *) &killPlayThread, 0, &thread_id);
		if(!play_thread_handle)
			return FALSE;
		
		// 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 TRUE;
}

//-----------------------------------------------------------------------------

BOOL Pause(LPCSTR medianame, int flags)
{
	if(QCDCallbacks->toPlayer.OutputPause(flags))
	{
		// send back pause/unpause notification
		QCDCallbacks->toPlayer.PlayPaused(medianame, flags);
		paused = flags;
		return TRUE;
	}
	return FALSE;
}

//-----------------------------------------------------------------------------

BOOL Stop(LPCSTR medianame, int flags)
{
	if(medianame && *medianame && stricmp(lastfn, medianame) == 0)
	{
		sQCDCallbacks.toPlayer.OutputStop(flags);
		
		killPlayThread = 1;
		if(play_thread_handle != INVALID_HANDLE_VALUE)
		{
			if(WaitForSingleObject(play_thread_handle, INFINITE) == WAIT_TIMEOUT)
			{
//				MessageBox(hwndPlayer, "FAAD thread kill timeout", "debug", 0);
				TerminateThread(play_thread_handle,0);
			}
			CloseHandle(play_thread_handle);
			play_thread_handle = INVALID_HANDLE_VALUE;
		}

		if (oldAPIs)
			QCDCallbacks->toPlayer.PlayStopped(lastfn);
		
		lastfn[0] = 0;
	}

	return TRUE;
}

int aac_seek(int pos_ms, int *sktable)
{
    double offset_sec;

    offset_sec = pos_ms / 1000.0;
    if(!current_file_mode)
    {
        seek_filestream(infile, sktable[(int)(offset_sec+0.5)], FILE_BEGIN);

        bytecount = sktable[(int)(offset_sec+0.5)];
        buffercount = 0;
        read_buffer_filestream(infile, buffer, 768*2);
    }
	else
	{
        memmap_index = sktable[(int)(offset_sec+0.5)];
    }

    return 0;
}

//-----------------------------------------------------------------------------

void SetVolume(int levelleft, int levelright, int flags)
{
	QCDCallbacks->toPlayer.OutputSetVol(levelleft, levelright, flags);
}

//-----------------------------------------------------------------------------

BOOL GetCurrentPosition(LPCSTR medianame, long *track, long *offset)
{
	return QCDCallbacks->toPlayer.OutputGetCurrentPosition((UINT*)offset, 0);
}

//-----------------------------------------------------------------------------

BOOL GetTrackExtents(LPCSTR medianame, TrackExtents *ext, int flags)
{
    faadAACInfo tmp;

    if(get_AAC_format((char*)medianame, &tmp, NULL, NULL, 1))
		return FALSE;

	ext->track = 1;
	ext->start = 0;
	ext->end = tmp.length;
	ext->bytesize = tmp.bitrate * tmp.length;
	ext->unitpersec = 1000;

	return TRUE;
}

//--------------------------for play thread-------------------------------------

int last_frame;

DWORD WINAPI PlayThread(void *b)
{
    BOOL done = FALSE, updatePos = FALSE;
	int decode_pos_ms = 0; // current decoding position, in milliseconds
    int l;
	int decoded_frames=0;
	int br_calc_frames=0;
	int br_bytes_consumed=0;
    unsigned long bytesconsumed;

    last_frame = 0;

	if(!done)
	{
		// open outputdevice
		WAVEFORMATEX wf;
		wf.wFormatTag = WAVE_FORMAT_PCM;
		wf.cbSize = 0;
		wf.nChannels = file_info.channels;
		wf.wBitsPerSample = 16;
		wf.nSamplesPerSec = file_info.sampling_rate;
		wf.nBlockAlign = wf.nChannels * wf.wBitsPerSample / 8;
		wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
		if (!QCDCallbacks->toPlayer.OutputOpen(lastfn, &wf))
		{
			show_error("Error: Failed openning output plugin!");
			done = TRUE; // cannot open sound device
		}
	}

    while (! *((int *)b) )
    {
 		/********************** SEEK ************************/
       if (!done && seek_needed >= 0)
	   {
            int seconds;

            // Round off to a second
            seconds = seek_needed - (seek_needed%1000);
			QCDCallbacks->toPlayer.OutputFlush(decode_pos_ms);
            aac_seek(seconds, seek_table);
            decode_pos_ms = seconds;
			decoded_frames = 0;
			br_calc_frames = 0;
			br_bytes_consumed = 0;

			seek_needed = -1;
			updatePos = 1;
	   }

		/********************* QUIT *************************/
		if (done)
		{
			if (QCDCallbacks->toPlayer.OutputDrain(0) && !(seek_needed >= 0))
			{
				play_thread_handle = INVALID_HANDLE_VALUE;
				QCDCallbacks->toPlayer.OutputStop(STOPFLAG_PLAYDONE);
				QCDCallbacks->toPlayer.PlayDone(lastfn);
			}
			else if (seek_needed >= 0)
			{
				done = FALSE;
				continue;
			}
			break;
		}

        /******************* DECODE TO BUFFER ****************/
		else
        {
			if (current_file_mode)
				bytesconsumed = PlayThread_memmap();
			else
				bytesconsumed = PlayThread_file();

			if(last_frame)
				done = TRUE;
			else
			{

				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)
				{
					AudioInfo vai;
					vai.struct_size = sizeof(AudioInfo);
					vai.frequency = file_info.sampling_rate;
					vai.bitrate = (int)((br_bytes_consumed * 8) / (decoded_frames / 43.07));
					vai.mode = (channels == 2) ? 0 : 3;
					vai.layer = 0;
					vai.level = file_info.version;
					QCDCallbacks->Service(opSetAudioInfo, &vai, sizeof(AudioInfo), 0);

					br_calc_frames = 0;
				}

                if (!killPlayThread && (frameInfo.samples > 0))
                {
                    //update the time display
					if (updatePos)
					{
						QCDCallbacks->toPlayer.PositionUpdate(decode_pos_ms);
						updatePos = 0;
					}
					
					{
						WriteDataStruct wd;

						l = frameInfo.samples * sizeof(short);

						decode_pos_ms += (1024*1000)/file_info.sampling_rate;
						
						wd.bytelen = l;
						wd.data = sample_buffer;
						wd.markerend = 0;
						wd.markerstart = decode_pos_ms;
						wd.bps = 16;
						wd.nch = frameInfo.channels;
						wd.numsamples =l/file_info.channels/(16/8);
						wd.srate = file_info.sampling_rate;
						
						if (!QCDCallbacks->toPlayer.OutputWrite(&wd))
							done = TRUE;
					}
				}
			}
		}
        Sleep(10);
    }

	// close up
	play_thread_handle = INVALID_HANDLE_VALUE;

	faacDecClose(hDecoder);
	hDecoder = INVALID_HANDLE_VALUE;
	close_filestream(infile);
	infile = NULL;

	if(seek_table)
	{
		free(seek_table);
		seek_table = NULL;
		seek_table_length = 0;
	}

	if(buffer)
	{
		LocalFree(buffer);
		buffer = NULL;
	}
	if(memmap_buffer)
	{
		LocalFree(memmap_buffer);
		memmap_buffer = NULL;
	}

    return 0;
}

// thread play funcs
int PlayThread_memmap()
{
    sample_buffer = (char*)faacDecDecode(hDecoder, &frameInfo,
        memmap_buffer + memmap_index, fileread - memmap_index - 1);
    if (frameInfo.error)
    {
//        show_error(faacDecGetErrorMessage(frameInfo.error));
        last_frame = 1;
    }

    memmap_index += frameInfo.bytesconsumed;
    if (memmap_index >= fileread)
        last_frame = 1;

    return frameInfo.bytesconsumed;
}

int PlayThread_file()
{
    int k;

    if (buffercount > 0)
	{
        for (k = 0; k < (768*2 - buffercount); k++)
            buffer[k] = buffer[k + buffercount];

        read_buffer_filestream(infile, buffer + (768*2) - buffercount, buffercount);
        buffercount = 0;
    }

    sample_buffer = (char*)faacDecDecode(hDecoder, &frameInfo, buffer, 768*2);
    if (frameInfo.error)
    {
//        show_error(faacDecGetErrorMessage(frameInfo.error));
        last_frame = 1;
    }

    buffercount += frameInfo.bytesconsumed;

    bytecount += frameInfo.bytesconsumed;
    if (bytecount >= fileread)
        last_frame = 1;

    return frameInfo.bytesconsumed;
}

// tag
int id3v2_tag(unsigned char *buffer)
{
    if (StringComp(buffer, "ID3", 3) == 0)
	{
        unsigned long tagsize;

        /* high bit is not used */
        tagsize = (buffer[6] << 21) | (buffer[7] << 14) |
            (buffer[8] <<  7) | (buffer[9] <<  0);

        tagsize += 10;

        return tagsize;
    }
	else
	{
        return 0;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -