From f44a93685ae651a08b51a2688a1c8d4c9ae2d28e Mon Sep 17 00:00:00 2001 From: tobigun Date: Fri, 8 May 2009 15:00:25 +0000 Subject: checkin of trunk-copy as base for cmake test git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/branches/experimental@1716 b956fd51-792f-4845-bead-9b4dfca2ff2c --- cmake/src/screens/UScreenEditConvert.pas | 657 +++++++++++++++++++++++++++++++ 1 file changed, 657 insertions(+) create mode 100644 cmake/src/screens/UScreenEditConvert.pas (limited to 'cmake/src/screens/UScreenEditConvert.pas') diff --git a/cmake/src/screens/UScreenEditConvert.pas b/cmake/src/screens/UScreenEditConvert.pas new file mode 100644 index 00000000..361a3be7 --- /dev/null +++ b/cmake/src/screens/UScreenEditConvert.pas @@ -0,0 +1,657 @@ +{* UltraStar Deluxe - Karaoke Game + * + * UltraStar Deluxe is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + *} + +unit UScreenEditConvert; + +interface + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + +{$I switches.inc} + +uses + UMenu, + SDL, + {$IFDEF UseMIDIPort} + MidiFile, + MidiOut, + {$ENDIF} + ULog, + USongs, + USong, + UMusic, + UThemes; + +type + TNote = record + Event: integer; + EventType: integer; + Channel: integer; + Start: real; + Len: real; + Data1: integer; + Data2: integer; + Str: string; + end; + + TTrack = record + Note: array of TNote; + Name: string; + Hear: boolean; + Status: set of (notes, lyrics); + end; + + TNuta = record + Start: integer; + Len: integer; + Tone: integer; + Lyric: string; + NewSentence: boolean; + end; + + TArrayTrack = array of TTrack; + + TScreenEditConvert = class(TMenu) + public + ATrack: TArrayTrack; // actual track +// Track: TArrayTrack; + Channel: TArrayTrack; + ColR: array[0..100] of real; + ColG: array[0..100] of real; + ColB: array[0..100] of real; + Len: real; + Sel: integer; + Selected: boolean; +// FileName: string; + + {$IFDEF UseMIDIPort} + MidiFile: TMidiFile; + MidiTrack: TMidiTrack; + MidiEvent: pMidiEvent; + MidiOut: TMidiOutput; + {$ENDIF} + + Song: TSong; + Lines: TLines; + BPM: real; + Ticks: real; + Note: array of TNuta; + + procedure AddLyric(Start: integer; Text: string); + procedure Extract; + + {$IFDEF UseMIDIPort} + procedure MidiFile1MidiEvent(event: PMidiEvent); + {$ENDIF} + + function SelectedNumber: integer; + constructor Create; override; + procedure onShow; override; + function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override; + function Draw: boolean; override; + procedure onHide; override; + end; + +var + ConversionFileName: string; + +implementation + +uses + SysUtils, + TextGL, + gl, + UDrawTexture, + UFiles, + UGraphic, + UIni, + UMain, + UPath, + USkins; + +function TScreenEditConvert.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; +begin + Result := true; + if (PressedDown) then + begin // Key Down + // check normal keys + case WideCharUpperCase(CharCode)[1] of + 'Q': + begin + Result := false; + Exit; + end; + end; + + // check special keys + case PressedKey of + SDLK_ESCAPE, + SDLK_BACKSPACE : + begin + {$IFDEF UseMIDIPort} + MidiFile.StopPlaying; + {$ENDIF} + AudioPlayback.PlaySound(SoundLib.Back); + FadeTo(@ScreenEdit); + end; + + SDLK_RETURN: + begin + if Interaction = 0 then + begin + AudioPlayback.PlaySound(SoundLib.Start); + ScreenOpen.BackScreen := @ScreenEditConvert; + FadeTo(@ScreenOpen); + end; + + if Interaction = 1 then + begin + Selected := false; + {$IFDEF UseMIDIPort} + MidiFile.OnMidiEvent := MidiFile1MidiEvent; +// MidiFile.GoToTime(MidiFile.GetTrackLength div 2); + MidiFile.StartPlaying; + {$ENDIF} + end; + + if Interaction = 2 then + begin + Selected := true; + {$IFDEF UseMIDIPort} + MidiFile.OnMidiEvent := nil; + {$ENDIF} + {for T := 0 to High(ATrack) do + begin + if ATrack[T].Hear then + begin + MidiTrack := MidiFile.GetTrack(T); + MidiTrack.OnMidiEvent := MidiFile1MidiEvent; + end; + end; + MidiFile.StartPlaying;//} + end; + + if Interaction = 3 then + begin + if SelectedNumber > 0 then + begin + Extract; + SaveSong(Song, Lines, ChangeFileExt(ConversionFileName, '.txt'), false); + end; + end; + + end; + + SDLK_SPACE: + begin +// ATrack[Sel].Hear := not ATrack[Sel].Hear; + if Notes in ATrack[Sel].Status then + begin + ATrack[Sel].Status := ATrack[Sel].Status - [Notes]; + if Lyrics in ATrack[Sel].Status then + ATrack[Sel].Status := ATrack[Sel].Status - [Lyrics] + else + ATrack[Sel].Status := ATrack[Sel].Status + [Lyrics]; + end + else + ATrack[Sel].Status := ATrack[Sel].Status + [Notes]; + +{ if Selected then + begin + MidiTrack := MidiFile.GetTrack(Sel); + if Track[Sel].Hear then + MidiTrack.OnMidiEvent := MidiFile1MidiEvent + else + MidiTrack.OnMidiEvent := nil; + end;} + end; + + SDLK_RIGHT: + begin + InteractNext; + end; + + SDLK_LEFT: + begin + InteractPrev; + end; + + SDLK_DOWN: + begin + Inc(Sel); + if Sel > High(ATrack) then + Sel := 0; + end; + SDLK_UP: + begin + Dec(Sel); + if Sel < 0 then + Sel := High(ATrack); + end; + end; + end; +end; + +procedure TScreenEditConvert.AddLyric(Start: integer; Text: string); +var + N: integer; +begin + for N := 0 to High(Note) do + begin + if Note[N].Start = Start then + begin + // check for new sentece + if Copy(Text, 1, 1) = '\' then + Delete(Text, 1, 1); + if Copy(Text, 1, 1) = '/' then + begin + Delete(Text, 1, 1); + Note[N].NewSentence := true; + end; + + // overwrite lyric od append + if Note[N].Lyric = '-' then + Note[N].Lyric := Text + else + Note[N].Lyric := Note[N].Lyric + Text; + end; + end; +end; + +procedure TScreenEditConvert.Extract; +var + T: integer; + C: integer; + N: integer; + Nu: integer; + NoteTemp: TNuta; + Move: integer; + Max, Min: integer; +begin + // song info + Song.Title := ''; + Song.Artist := ''; + Song.Mp3 := ''; + Song.Resolution := 4; + SetLength(Song.BPM, 1); + Song.BPM[0].BPM := BPM*4; + + SetLength(Note, 0); + + // extract notes + for T := 0 to High(ATrack) do + begin +// if ATrack[T].Hear then +// begin + if Notes in ATrack[T].Status then + begin + for N := 0 to High(ATrack[T].Note) do + begin + if (ATrack[T].Note[N].EventType = 9) and (ATrack[T].Note[N].Data2 > 0) then + begin + Nu := Length(Note); + SetLength(Note, Nu + 1); + Note[Nu].Start := Round(ATrack[T].Note[N].Start / Ticks); + Note[Nu].Len := Round(ATrack[T].Note[N].Len / Ticks); + Note[Nu].Tone := ATrack[T].Note[N].Data1 - 12*5; + Note[Nu].Lyric := '-'; + end; + end; + end; + end; + + // extract lyrics + for T := 0 to High(ATrack) do + begin +// if ATrack[T].Hear then +// begin + if Lyrics in ATrack[T].Status then + begin + for N := 0 to High(ATrack[T].Note) do + begin + if (ATrack[T].Note[N].EventType = 15) then + begin +// Log.LogStatus('<' + Track[T].Note[N].Str + '>', 'MIDI'); + AddLyric(Round(ATrack[T].Note[N].Start / Ticks), ATrack[T].Note[N].Str); + end; + end; + end; + end; + + // sort notes + for N := 0 to High(Note) do + for Nu := 0 to High(Note)-1 do + if Note[Nu].Start > Note[Nu+1].Start then + begin + NoteTemp := Note[Nu]; + Note[Nu] := Note[Nu+1]; + Note[Nu+1] := NoteTemp; + end; + + // move to 0 at beginning + Move := Note[0].Start; + for N := 0 to High(Note) do + Note[N].Start := Note[N].Start - Move; + + // copy notes + SetLength(Lines.Line, 1); + Lines.Number := 1; + Lines.High := 0; + + C := 0; + N := 0; + Lines.Line[C].HighNote := -1; + + for Nu := 0 to High(Note) do + begin + if Note[Nu].NewSentence then // new line + begin + SetLength(Lines.Line, Length(Lines.Line)+1); + Lines.Number := Lines.Number + 1; + Lines.High := Lines.High + 1; + C := C + 1; + N := 0; + SetLength(Lines.Line[C].Note, 0); + Lines.Line[C].HighNote := -1; + + //Calculate Start of the Last Sentence + if (C > 0) and (Nu > 0) then + begin + Max := Note[Nu].Start; + Min := Note[Nu-1].Start + Note[Nu-1].Len; + + case (Max - Min) of + 0: Lines.Line[C].Start := Max; + 1: Lines.Line[C].Start := Max; + 2: Lines.Line[C].Start := Max - 1; + 3: Lines.Line[C].Start := Max - 2; + else + if ((Max - Min) > 4) then + Lines.Line[C].Start := Min + 2 + else + Lines.Line[C].Start := Max; + + end; // case + + end; + end; + + // create space for new note + SetLength(Lines.Line[C].Note, Length(Lines.Line[C].Note)+1); + + // initialize note + Lines.Line[C].Note[N].Start := Note[Nu].Start; + Lines.Line[C].Note[N].Length := Note[Nu].Len; + Lines.Line[C].Note[N].Tone := Note[Nu].Tone; + Lines.Line[C].Note[N].Text := Note[Nu].Lyric; + //All Notes are Freestyle when Converted Fix: + Lines.Line[C].Note[N].NoteType := ntNormal; + Inc(N); + end; +end; + +function TScreenEditConvert.SelectedNumber: integer; +var + T: integer; // track +begin + Result := 0; + for T := 0 to High(ATrack) do +// if ATrack[T].Hear then +// Inc(Result); + if Notes in ATrack[T].Status then + Inc(Result); +end; + +{$IFDEF UseMIDIPort} +procedure TScreenEditConvert.MidiFile1MidiEvent(event: PMidiEvent); +begin +// Log.LogStatus(IntToStr(event.event), 'MIDI'); + MidiOut.PutShort(event.event, event.data1, event.data2); +end; +{$ENDIF} + +constructor TScreenEditConvert.Create; +var + P: integer; +begin + inherited Create; + AddButton(40, 20, 100, 40, Skin.GetTextureFileName('ButtonF')); + AddButtonText(15, 5, 0, 0, 0, 'Open'); +// Button[High(Button)].Text[0].Size := 11; + + AddButton(160, 20, 100, 40, Skin.GetTextureFileName('ButtonF')); + AddButtonText(25, 5, 0, 0, 0, 'Play'); + + AddButton(280, 20, 200, 40, Skin.GetTextureFileName('ButtonF')); + AddButtonText(25, 5, 0, 0, 0, 'Play Selected'); + + AddButton(500, 20, 100, 40, Skin.GetTextureFileName('ButtonF')); + AddButtonText(20, 5, 0, 0, 0, 'Save'); + +{ MidiOut := TMidiOutput.Create(nil); +// MidiOut.Close; +// MidiOut.DeviceID := 0; + if Ini.Debug = 1 then + MidiOut.ProductName := 'Microsoft GS Wavetable SW Synth'; // for my kxproject without midi table + Log.LogStatus(MidiOut.ProductName, 'MIDI'); + MidiOut.Open; +// MidiOut.SetVolume(100, 100); // temporary} + + ConversionFileName := GamePath + 'file.mid'; + {$IFDEF UseMIDIPort} + MidiFile := TMidiFile.Create(nil); + {$ENDIF} + + for P := 0 to 100 do + begin + ColR[P] := Random(10)/10; + ColG[P] := Random(10)/10; + ColB[P] := Random(10)/10; + end; + +end; + +procedure TScreenEditConvert.onShow; +var + T: integer; // track + N: integer; // note + C: integer; // channel + CN: integer; // channel note +begin + inherited; + +{$IFDEF UseMIDIPort} + MidiOut := TMidiOutput.Create(nil); + if Ini.Debug = 1 then + MidiOut.ProductName := 'Microsoft GS Wavetable SW Synth'; // for my kxproject without midi table + Log.LogStatus(MidiOut.ProductName, 'MIDI'); + MidiOut.Open; + + if FileExists(ConversionFileName) then + begin + MidiFile.Filename := ConversionFileName; + MidiFile.ReadFile; + + Len := 0; + Sel := 0; + BPM := MidiFile.Bpm; + Ticks := MidiFile.TicksPerQuarter / 4; + +{ for T := 0 to MidiFile.NumberOfTracks-1 do + begin + SetLength(Track, Length(Track)+1); + MidiTrack := MidiFile.GetTrack(T); + MidiTrack.OnMidiEvent := MidiFile1MidiEvent; + Track[T].Name := MidiTrack.getName; + + for N := 0 to MidiTrack.getEventCount-1 do + begin + SetLength(Track[T].Note, Length(Track[T].Note)+1); + MidiEvent := MidiTrack.GetEvent(N); + Track[T].Note[N].Start := MidiEvent.time; + Track[T].Note[N].Len := MidiEvent.len; + Track[T].Note[N].Event := MidiEvent.event; + Track[T].Note[N].EventType := MidiEvent.event div 16; + Track[T].Note[N].Channel := MidiEvent.event and 15; + Track[T].Note[N].Data1 := MidiEvent.data1; + Track[T].Note[N].Data2 := MidiEvent.data2; + Track[T].Note[N].Str := MidiEvent.str; + + if Track[T].Note[N].Start + Track[T].Note[N].Len > Len then + Len := Track[T].Note[N].Start + Track[T].Note[N].Len; + end; + end;} + + SetLength(Channel, 16); + for T := 0 to 15 do + begin + Channel[T].Name := IntToStr(T+1); + SetLength(Channel[T].Note, 0); + Channel[T].Status := []; + end; + + for T := 0 to MidiFile.NumberOfTracks-1 do + begin + MidiTrack := MidiFile.GetTrack(T); + MidiTrack.OnMidiEvent := MidiFile1MidiEvent; + + for N := 0 to MidiTrack.getEventCount-1 do + begin + MidiEvent := MidiTrack.GetEvent(N); + C := MidiEvent.event and 15; + + CN := Length(Channel[C].Note); + SetLength(Channel[C].Note, CN+1); + + Channel[C].Note[CN].Start := MidiEvent.time; + Channel[C].Note[CN].Len := MidiEvent.len; + Channel[C].Note[CN].Event := MidiEvent.event; + Channel[C].Note[CN].EventType := MidiEvent.event div 16; + Channel[C].Note[CN].Channel := MidiEvent.event and 15; + Channel[C].Note[CN].Data1 := MidiEvent.data1; + Channel[C].Note[CN].Data2 := MidiEvent.data2; + Channel[C].Note[CN].Str := MidiEvent.str; + + if Channel[C].Note[CN].Start + Channel[C].Note[CN].Len > Len then + Len := Channel[C].Note[CN].Start + Channel[C].Note[CN].Len; + end; + end; + ATrack := Channel; + + end; + + Interaction := 0; +{$ENDIF} +end; + +function TScreenEditConvert.Draw: boolean; +var + Count: integer; + Count2: integer; + Bottom: real; + X: real; + Y: real; + H: real; + YSkip: real; +begin + // draw static menu + inherited Draw; + + Y := 100; + + H := Length(ATrack)*40; + if H > 480 then + H := 480; + Bottom := Y + H; + + YSkip := H / Length(ATrack); + + // select + DrawQuad(10, Y+Sel*YSkip, 780, YSkip, 0.8, 0.8, 0.8); + + // selected - now me use Status System + for Count := 0 to High(ATrack) do + if ATrack[Count].Hear then + DrawQuad(10, Y+Count*YSkip, 50, YSkip, 0.8, 0.3, 0.3); + glColor3f(0, 0, 0); + for Count := 0 to High(ATrack) do + begin + if Notes in ATrack[Count].Status then + begin + SetFontPos(25, Y + Count*YSkip + 10); + SetFontSize(15); + glPrint('N'); + end; + if Lyrics in ATrack[Count].Status then + begin + SetFontPos(40, Y + Count*YSkip + 10); + SetFontSize(15); + glPrint('L'); + end; + end; + + DrawLine(10, Y, 10, Bottom, 0, 0, 0); + DrawLine(60, Y, 60, Bottom, 0, 0, 0); + DrawLine(790, Y, 790, Bottom, 0, 0, 0); + + for Count := 0 to Length(ATrack) do + DrawLine(10, Y+Count*YSkip, 790, Y+Count*YSkip, 0, 0, 0); + + for Count := 0 to High(ATrack) do + begin + SetFontPos(11, Y + 10 + Count*YSkip); + SetFontSize(15); + glPrint(ATrack[Count].Name); + end; + + for Count := 0 to High(ATrack) do + for Count2 := 0 to High(ATrack[Count].Note) do + begin + if ATrack[Count].Note[Count2].EventType = 9 then + DrawQuad(60 + ATrack[Count].Note[Count2].Start/Len * 725, Y + (Count+1)*YSkip - ATrack[Count].Note[Count2].Data1*35/127, 3, 3, ColR[Count], ColG[Count], ColB[Count]); + if ATrack[Count].Note[Count2].EventType = 15 then + DrawLine(60 + ATrack[Count].Note[Count2].Start/Len * 725, Y + 0.75 * YSkip + Count*YSkip, 60 + ATrack[Count].Note[Count2].Start/Len * 725, Y + YSkip + Count*YSkip, ColR[Count], ColG[Count], ColB[Count]); + end; + + // playing line + {$IFDEF UseMIDIPort} + X := 60 + MidiFile.GetCurrentTime/MidiFile.GetTrackLength*730; + {$ENDIF} + DrawLine(X, Y, X, Bottom, 0.3, 0.3, 0.3); + + Result := true; +end; + +procedure TScreenEditConvert.onHide; +begin +{$IFDEF UseMIDIPort} + MidiOut.Close; + MidiOut.Free; +{$ENDIF} +end; + +end. -- cgit v1.2.3