Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

project update from 24Z WIMU #5

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions 24Z_update.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
## Added functionalities:

- Miditok library upgrade: from 2.1.7 to 3.0.4
- Added PerTok tokenizator
- New logics of corresponding notes with tokens (forced by library upgrade)
- New parameters in configuration (mostly for PetTok): use_programs, use_microtiming, ticks_per_quarter, max_microtiming_shift, num_microtiming_bins
- Default tokenizator classes, now associating notes to tokens is run after we receive tokens, unifed functions for all tokenizers depending on "use_programs" parameter usage

### frontend:

- New design in general
- Subtle animations
- New piano roll- high resoultion, stable keybord so it does not vanish with scrolling
- Tokens can be paginated and scaled
- New audio player

![Screenshot of app](img/app_screenshot.png)

## Deployment

You can see an example deployment on Railway [here](https://miditok-visualizer-production-frontend.up.railway.app/)
As long as we're above our trial limit on Railway

## Running locally:

You can use same commands as before to run the project locally.

### Frontend

Basic run:

```sh
cd frontend
npm install
npm run dev
```

Using Docker:

```sh
cd frontend
docker build . -t frontend
docker run frontend -p 3000:3000
```

### Backend

Basic run:

```sh
cd backend
poetry shell
poetry install
python -m core.main
```

or

```sh
poetry run python -m core.main
```

Using Docker:

```sh
cd backend
DOCKER_BUILDKIT=1 docker build --target=runtime . -t backend
docker run backend -p 8000:8000
```

### All at once:

```sh
docker-compose up
```

## Contributors

- Karol Bogumił
- Maksymilian Banach
- Jakub Przesmycki
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,3 @@ We use:
- Kacper Stefański
- Konstantin Panov
- Piotr Malesa

15 changes: 9 additions & 6 deletions backend/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
default_language_version:
python: python3.11.6
python: python3.11.9
repos:
- repo: local
hooks:
Expand All @@ -15,14 +15,17 @@ repos:
entry: isort
args: ["--check", "--diff"]
types: [python]
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.9.1
hooks:
- id: ruff
name: ruff
language: system
entry: ruff
args: ["--force-exclude"]
types: [python]
args: ["--fix"]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.14.1
hooks:
- id: mypy
name: mypy
language: system
entry: mypy
args: ["--no-incremental", "--ignore-missing-imports"]
types: [python]
23 changes: 19 additions & 4 deletions backend/core/api/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import json
import logging.config
from typing import List

from fastapi import Body, FastAPI, File, HTTPException, UploadFile
from fastapi.exceptions import RequestValidationError
Expand All @@ -16,7 +15,12 @@

app = FastAPI()

origins = ["http://localhost:3000", "https://wimu-frontend-ccb0bbc023d3.herokuapp.com"]
origins = [
"http://localhost:3000",
"https://wimu-frontend-ccb0bbc023d3.herokuapp.com",
"https://miditok-visualizer-production-frontend.up.railway.app",
]


app.add_middleware(
CORSMiddleware, allow_origins=origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"]
Expand All @@ -32,6 +36,11 @@ async def validation_exception_handler(request, exc):
)


def save_to_file(data, filename): # debug function
with open(filename, "w", encoding="utf-8") as f:
f.write(str(data))


@app.post("/process")
async def process(config: ConfigModel = Body(...), file: UploadFile = File(...)) -> JSONResponse:
try:
Expand All @@ -40,15 +49,21 @@ async def process(config: ConfigModel = Body(...), file: UploadFile = File(...))
midi_bytes: bytes = await file.read()
tokens, notes = tokenize_midi_file(config, midi_bytes)
serialized_tokens = json.dumps(tokens, cls=TokSequenceEncoder)
serialized_notes = [[note.__dict__ for note in track_notes] for track_notes in notes]
note_id = 1
serialized_notes = []
for track_notes in notes:
serialized_track = [{**note.__dict__, "note_id": note_id + i} for i, note in enumerate(track_notes)]
serialized_notes.append(serialized_track)
note_id += len(track_notes)

metrics: MusicInformationData = retrieve_information_from_midi(midi_bytes)
return JSONResponse(
content={
"success": True,
"data": {
"tokens": json.loads(serialized_tokens),
"notes": serialized_notes,
"metrics": json.loads(metrics.model_dump_json())
"metrics": json.loads(metrics.model_dump_json()),
},
"error": None,
}
Expand Down
1 change: 1 addition & 0 deletions backend/core/api/logging_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ async def _execute_request(self, call_next: Callable, request: Request, request_

except Exception as e:
self._logger.exception({"path": request.url.path, "method": request.method, "reason": e})
return Response(content="Internal Server Error", status_code=500)


class AsyncIteratorWrapper:
Expand Down
24 changes: 13 additions & 11 deletions backend/core/api/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,35 @@

class ConfigModel(
BaseModel
): # TODO: beat_res, beat_res_rest, chord_maps, chord_tokens_with_root_note, chord_unknown, time_signature_range
tokenizer: Literal["REMI", "REMIPlus", "MIDILike", "TSD", "Structured", "CPWord", "Octuple", "MuMIDI", "MMM"]
): # TODO: dynamic beat_res, beat_res_rest, chord_maps, chord_tokens_with_root_note, chord_unknown, time_signature_range
tokenizer: Literal[
"REMI", "REMIPlus", "MIDILike", "TSD", "Structured", "CPWord", "Octuple", "MuMIDI", "MMM", "PerTok"
]
pitch_range: Annotated[list[Annotated[int, Field(ge=0, le=127)]], Field(min_length=2, max_length=2)]
nb_velocities: Annotated[int, Field(ge=0, le=127)]
num_velocities: Annotated[int, Field(ge=0, le=127)]
special_tokens: list[str]
use_chords: StrictBool
use_rests: StrictBool
use_tempos: StrictBool
use_time_signatures: StrictBool
use_sustain_pedals: StrictBool
use_pitch_bends: StrictBool
use_programs: StrictBool
nb_tempos: NonNegativeInt
tempo_range: Annotated[list[NonNegativeInt], Field(min_length=2, max_length=2)]
log_tempos: StrictBool
delete_equal_successive_tempo_changes: StrictBool
sustain_pedal_duration: StrictBool
pitch_bend_range: Annotated[list[int], Field(min_length=3, max_length=3)]
delete_equal_successive_time_sig_changes: StrictBool
use_programs: StrictBool
programs: Optional[Annotated[list[int], Field(min_length=2, max_length=2)]]
one_token_stream_for_programs: Optional[StrictBool]
program_changes: Optional[StrictBool]
# added for pertok
use_microtiming: StrictBool
ticks_per_quarter: Annotated[int, Field(ge=24, le=960)]
max_microtiming_shift: Annotated[float, Field(ge=0, le=1)]
num_microtiming_bins: Annotated[int, Field(ge=1, le=64)]

@model_validator(mode="before")
@classmethod
Expand All @@ -56,12 +63,6 @@ def check_valid_ranges(cls, values):
if min_pitch_bend > max_pitch_bend:
raise ValueError("max_pitch_bend must be greater or to than min_pitch_bend")

# if values.programs is not None:
# min_program = Optional[values.programs[0]]
# max_program = Optional[values.programs[1]]
# if min_program > max_program:
# raise ValueError('max_program must be greater or equal to min_program')

return values


Expand Down Expand Up @@ -100,10 +101,11 @@ class MetricsData:
empty_beat_rate: float
drum_pattern_consistency: float


@dataclass
class Note:
pitch: int
name: str
start: int
end: int
velocity: int
velocity: int
Loading