示例#1
0
static int SeekSet0 (demux_t *demux)
{
    stream_t *stream = demux->s;
    demux_sys_t *sys = demux->p_sys;

    /* Default SMF tempo is 120BPM, i.e. half a second per quarter note */
    date_Init (&sys->pts, sys->ppqn * 2, 1);
    date_Set (&sys->pts, VLC_TS_0);
    sys->pulse = 0;
    sys->tick = VLC_TS_0;

    for (unsigned i = 0; i < sys->trackc; i++)
    {
        mtrk_t *tr = sys->trackv + i;

        tr->offset = 0;
        tr->next = 0;
        /* Why 0xF6 (Tuning Calibration)?
         * Because it has zero bytes of data, so the parser will detect the
         * error if the first event uses running status. */
        tr->running_event = 0xF6;

        if (stream_Seek (stream, tr->start)
         || ReadDeltaTime (stream, tr))
        {
            msg_Err (demux, "fatal parsing error");
            return -1;
        }
    }

    return 0;
}
示例#2
0
文件: smf.c 项目: CSRedRat/vlc
/*****************************************************************************
 * Demux: read chunks and send them to the synthesizer
 *****************************************************************************
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 *****************************************************************************/
static int Demux (demux_t *p_demux)
{
    stream_t *s = p_demux->s;
    demux_sys_t *p_sys = p_demux->p_sys;
    uint64_t     pulse = p_sys->pulse, next_pulse = UINT64_MAX;

    if (pulse == UINT64_MAX)
        return 0; /* all tracks are done */

    es_out_Control (p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + date_Get (&p_sys->pts));

    for (unsigned i = 0; i < p_sys->trackc; i++)
    {
        mtrk_t *track = p_sys->trackv + i;

        while (track->next == pulse)
        {
            if (HandleMessage (p_demux, track)
             || ReadDeltaTime (s, track))
            {
                msg_Err (p_demux, "fatal parsing error");
                return VLC_EGENERIC;
            }
        }

        if (track->next < next_pulse)
            next_pulse = track->next;
    }

    mtime_t cur_tick = (date_Get (&p_sys->pts) + 9999) / 10000, last_tick;
    if (next_pulse != UINT64_MAX)
        last_tick = date_Increment (&p_sys->pts, next_pulse - pulse) / 10000;
    else
        last_tick = cur_tick + 1;

    /* MIDI Tick emulation (ping the decoder every 10ms) */
    while (cur_tick < last_tick)
    {
        block_t *tick = block_New (p_demux, 1);
        if (tick == NULL)
            break;

        tick->p_buffer[0] = 0xF9;
        tick->i_dts = tick->i_pts = VLC_TS_0 + cur_tick++ * 10000;
        es_out_Send (p_demux->out, p_sys->es, tick);
    }

    p_sys->pulse = next_pulse;

    return 1;
}
示例#3
0
文件: smf.c 项目: CSRedRat/vlc
/*****************************************************************************
 * Open: check file and initializes structures
 *****************************************************************************/
static int Open (vlc_object_t * p_this)
{
    demux_t       *p_demux = (demux_t *)p_this;
    stream_t      *stream = p_demux->s;
    demux_sys_t   *p_sys;
    const uint8_t *peek;
    unsigned       tracks, ppqn;
    bool     multitrack;

    /* (Try to) parse the SMF header */
    /* Header chunk always has 6 bytes payload */
    if (stream_Peek (stream, &peek, 14) < 14)
        return VLC_EGENERIC;

    /* Skip RIFF MIDI header if present */
    if (!memcmp (peek, "RIFF", 4) && !memcmp (peek + 8, "RMID", 4))
    {
        uint32_t riff_len = GetDWLE (peek + 4);

        msg_Dbg (p_this, "detected RIFF MIDI file (%u bytes)",
                 (unsigned)riff_len);
        if ((stream_Read (stream, NULL, 12) < 12))
            return VLC_EGENERIC;

        /* Look for the RIFF data chunk */
        for (;;)
        {
            char chnk_hdr[8];
            uint32_t chnk_len;

            if ((riff_len < 8)
             || (stream_Read (stream, chnk_hdr, 8) < 8))
                return VLC_EGENERIC;

            riff_len -= 8;
            chnk_len = GetDWLE (chnk_hdr + 4);
            if (riff_len < chnk_len)
                return VLC_EGENERIC;
            riff_len -= chnk_len;

            if (!memcmp (chnk_hdr, "data", 4))
                break; /* found! */

            if (stream_Read (stream, NULL, chnk_len) < (ssize_t)chnk_len)
                return VLC_EGENERIC;
        }

        /* Read real SMF header. Assume RIFF data chunk length is proper. */
        if (stream_Peek (stream, &peek, 14) < 14)
            return VLC_EGENERIC;
    }

    if (memcmp (peek, "MThd\x00\x00\x00\x06", 8))
        return VLC_EGENERIC;
    peek += 8;

    /* First word: SMF type */
    switch (GetWBE (peek))
    {
        case 0:
            multitrack = false;
            break;
        case 1:
            multitrack = true;
            break;
        default:
            /* We don't implement SMF2 (as do many) */
            msg_Err (p_this, "unsupported SMF file type %u", GetWBE (peek));
            return VLC_EGENERIC;
    }
    peek += 2;

    /* Second word: number of tracks */
    tracks = GetWBE (peek);
    peek += 2;
    if (!multitrack && (tracks != 1))
    {
        msg_Err (p_this, "invalid SMF type 0 file");
        return VLC_EGENERIC;
    }

    msg_Dbg (p_this, "detected Standard MIDI File (type %u) with %u track(s)",
             multitrack, tracks);

    /* Third/last word: timing */
    ppqn = GetWBE (peek);
    if (ppqn & 0x8000)
    {
        /* FIXME */
        msg_Err (p_this, "SMPTE timestamps not implemented");
        return VLC_EGENERIC;
    }
    else
    {
        msg_Dbg (p_this, " %u pulses per quarter note", ppqn);
    }

    p_sys = malloc (sizeof (*p_sys) + (sizeof (mtrk_t) * tracks));
    if (p_sys == NULL)
        return VLC_ENOMEM;

    /* We've had a valid SMF header - now skip it*/
    if (stream_Read (stream, NULL, 14) < 14)
        goto error;

    p_demux->pf_demux   = Demux;
    p_demux->pf_control = Control;
    p_demux->p_sys      = p_sys;

    /* Default SMF tempo is 120BPM, i.e. half a second per quarter note */
    date_Init (&p_sys->pts, ppqn * 2, 1);
    date_Set (&p_sys->pts, 0);
    p_sys->pulse        = 0;
    p_sys->ppqn         = ppqn;

    p_sys->trackc       = tracks;
    /* Prefetch track offsets */
    for (unsigned i = 0; i < tracks; i++)
    {
        uint8_t head[8];

        if (i > 0)
        {
            /* Seeking screws streaming up, but there is no way around this,
             * as SMF1 tracks are performed simultaneously.
             * Not a big deal as SMF1 are usually only a few kbytes anyway. */
            if (stream_Seek (stream,  p_sys->trackv[i-1].end))
            {
                msg_Err (p_this, "cannot build SMF index (corrupted file?)");
                goto error;
            }
        }

        for (;;)
        {
            if (stream_Read (stream, head, 8) < 8)
            {
                /* FIXME: don't give up if we have at least one valid track */
                msg_Err (p_this, "incomplete SMF chunk, file is corrupted");
                goto error;
            }

            if (memcmp (head, "MTrk", 4) == 0)
                break;

            msg_Dbg (p_this, "skipping unknown SMF chunk");
            stream_Read (stream, NULL, GetDWBE (head + 4));
        }

        p_sys->trackv[i].offset = stream_Tell (stream);
        p_sys->trackv[i].end = p_sys->trackv[i].offset + GetDWBE (head + 4);
        p_sys->trackv[i].next = 0;
        ReadDeltaTime (stream, p_sys->trackv + i);
        p_sys->trackv[i].running_event = 0xF6;
        /* Why 0xF6 (Tuning Calibration)?
         * Because it has zero bytes of data, so the parser will detect the
         * error if the first event uses running status. */
    }

    es_format_t  fmt;
    es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_MIDI);
    fmt.audio.i_channels = 2;
    fmt.audio.i_rate = 44100; /* dummy value */
    p_sys->es = es_out_Add (p_demux->out, &fmt);

    return VLC_SUCCESS;

error:
    free (p_sys);
    return VLC_EGENERIC;
}
示例#4
0
文件: HOSA.cpp 项目: soneek/vgmtrans
//==============================================================
//		Process of 1 Event
//--------------------------------------------------------------
//	Input
//		Nothing
//	Output
//		Nothing
//	Memo
//		SeqTrack::LoadTrack() から call される。
//==============================================================
bool HOSATrack::ReadEvent(void)
{

	//==================================
	//	[ Local 変数 ]
	//----------------------------------
	const		ULONG	beginOffset	= curOffset;					//start offset point

	const		BYTE	cCommand	= GetByte(curOffset++);			//command (op-code)
	const		BYTE	cCom_bit0	= (cCommand & 0x1F);			//length / contents
	const		BYTE	cCom_bit5	= (cCommand & 0x60) >> 5;		//Delta times
	const		BYTE	cCom_bit7	= (cCommand & 0x80) >> 7;		//0=Notes / 1=Controls

//	unsigned 	int					iMinLengthCounter;				//デルタタイム最小値
//				int					i;		//general
//	vector<char>::iterator			it_note;
//	vector<int unsigned >::iterator	it_Length;



	//==================================
	//	[ Process of "Delta time" and "Note off Event" ]
	//----------------------------------
	//Command用の(DeltaCounter==0)まで繰り返し。
	//while(iDeltaTimeCounter!=0){

	//	//Search the minimum length time [ticks]
	//	iMinLengthCounter	=	iDeltaTimeCounter;
	//	for(i=0;i<listLength.size();i++){
	//		if(iMinLengthCounter > listLength[i]){
	//			iMinLengthCounter = listLength[i];
	//		}
	//	}

	//	//Writing delta time.
	//	AddDelta(iMinLengthCounter);
	//	
	//	//Subtract the minimum length time from "Delta time" and "Length times"
	//	iDeltaTimeCounter	-=	iMinLengthCounter;
	//	for(i=0;i<listNote.size();i++){
	//		listLength[i] -= iMinLengthCounter;
	//	}

	//	//Search the ("Length times" == 0)
	//	it_note		= listNote.begin();
	//	it_Length	= listLength.begin();
	//	while(it_Length != listLength.end()){
	//		if(*it_Length==0){
	//			//Write "Note-off Event"
	//			AddNoteOffNoItem(*it_note);
	//			//Erase note-information from vector.
	//			it_note		= listNote.erase(it_note);
	//			it_Length	= listLength.erase(it_Length);
	//		} else {
	//			it_note++;
	//			it_Length++;
	//		}
	//	}
	//}



	//==================================
	//	[ Process of command (note / control) ]
	//----------------------------------

	//----------------------------------
	//	Command: Notes  (cCommand == 0x00 - 0x7F)
	if(cCom_bit7==0){

		//--------
		//[2]Update the default Note Number
		cNoteNum	= GetByte(curOffset++);

		//--------
		//[3]Update the default Delta time
		ReadDeltaTime(cCom_bit5, &iDeltaTimeCom);

		//--------
		//[4]Update the default Length
		iLengthTimeNote = GetShort(parentSeq->dwOffset + 0x10 + cCom_bit0*2);
		if(iLengthTimeNote==0){
//			iLengthTimeNote = ReadVarLen(curOffset);		//No count curOffset
			iLengthTimeNote = DecodeVariable();
		};

		//--------
		//[5]Update the default Velocity
		if(cNoteNum & 0x80){
			cNoteNum &= 0x7F;
			cVelocity = GetByte(curOffset++);
		};

		//--------
		//[3]Update the default Delta time (continuation)
		if(cCom_bit5==1){
			iDeltaTimeCom = iLengthTimeNote;	//Delta time is the same as note length.
		};
		iDeltaTimeNote = iDeltaTimeCom;			//Default delta time for Note.

		//--------
		//Write Note-On Event
		AddNoteByDur(beginOffset, curOffset-beginOffset, cNoteNum, cVelocity, iLengthTimeNote);


	//----------------------------------
	//	Command: Controls  (cCommand == 0x80 - 0x9F, 0xC0 - 0xFF)
	} else {
		if(cCom_bit5!=1){
			switch(cCom_bit0){
				//------------
				//End of Track
				case(0x00):
					AddEndOfTrack(beginOffset, curOffset-beginOffset);
					return false;
					break;
				//------------
				//Tempo
				case(0x01):
					cTempo = GetByte(curOffset++);
					AddTempoBPM(beginOffset, curOffset-beginOffset, cTempo);
					break;
				//------------
				//Reverb
				case(0x02):
					curOffset++;
					AddGenericEvent(beginOffset, curOffset-beginOffset, L"Reverb Depth", NULL, CLR_REVERB);
					break;
				//------------
				//Instrument
				case(0x03):
					cInstrument = GetByte(curOffset++);
					AddProgramChange(beginOffset, curOffset-beginOffset, cInstrument);
					break;
				//------------
				//Volume
				case(0x04):
					cVolume = GetByte(curOffset++);
					AddVol(beginOffset, curOffset-beginOffset, cVolume);
					break;
				//------------
				//Panpot
				case(0x05):
					cPanpot = GetByte(curOffset++);
					AddPan(beginOffset, curOffset-beginOffset, cPanpot);
					break;
				//------------
				//Expression
				case(0x06):
					cExpression = GetByte(curOffset++);
					AddExpression(beginOffset, curOffset-beginOffset, cExpression);
					break;
				//------------
				//Unknown
				case(0x07):
					curOffset++;
					curOffset++;
					AddUnknown(beginOffset, curOffset-beginOffset);
					break;
				//------------
				//Dal Segno. (Loop)
				case(0x09):
					curOffset++;
					AddGenericEvent(beginOffset, curOffset-beginOffset, L"Dal Segno.(Loop)", NULL, CLR_LOOP);
					break;
				//------------
				//Unknown
				case(0x0F):
					AddUnknown(beginOffset, curOffset-beginOffset);
					break;
				//------------
				//Unknowns
				default:
					curOffset++;
					AddUnknown(beginOffset, curOffset-beginOffset);
					break;
			}

			//--------
			//[3]Delta time
			ULONG	beginOffset2 = curOffset;
			ReadDeltaTime(cCom_bit5, &iDeltaTimeCom);
			if(curOffset != beginOffset2){
				AddGenericEvent(beginOffset2,curOffset-beginOffset2, L"Delta time", NULL, CLR_CHANGESTATE);
			};

	//----------------------------------
	//	Command: Notes  (cCommand == 0xA0 - 0xBF)
		} else {
			if(cCom_bit0 & 0x10){
				//Add (Command = 0xB0 - 0xBF)
				cNoteNum+=(cCom_bit0 & 0x0F);
			}else{
				//Sub (Command = 0xA0 - 0xAF)
				cNoteNum-=(cCom_bit0 & 0x0F);
			};
			//--------
			//Write Note-On Event
			AddNoteByDur(beginOffset, curOffset-beginOffset, cNoteNum, cVelocity, iLengthTimeNote);
			iDeltaTimeCom		= iDeltaTimeNote;
		}
	}

	//==================================
	//	[ Process of "Note" with note length ]
	//----------------------------------
	//if(fNoteOutput!=0){
	//	//Write "Note-on Event"
	//	AddNoteOn(beginOffset, curOffset-beginOffset, fNoteOutput, cVelocity);
	//	//Add note-information to vector.
	//	listNote.push_back(fNoteOutput);		//Note Number
	//	listLength.push_back(iLengthTimeNote);	//Length
	//	//Next delta time
	//	iDeltaTimeCom		= iDeltaTimeNote;
	//}



	//==================================
	//	[ Process of "Setting Delta time" ]
	//----------------------------------
	//iDeltaTimeCounter = iDeltaTimeCom;
	AddTime(iDeltaTimeCom);



	return true;

}