You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

129 lines
3.9 KiB

#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),
This application 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 3 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. If not, see <http://www.gnu.org/licenses/>.
"""
"""
This file handles various durations and their conversions.
"""
import logging; logger = logging.getLogger(__name__); logger.info("import")
from engine.config import METADATA
#Suggested import in other files:
#from template.engine.duration import DB, DL, D1, D2, D4, D8, D16, D32, D64, D128
#import template.engine.duration as duration
MAXIMUM_TICK_DURATION = 2**31-1
D4 = METADATA["quarterNoteInTicks"]
D8 = int(D4 / 2)
D16 = int(D8 / 2)
D32 = int(D16 / 2)
D64 = int(D32 / 2)
D128 = int(D64 / 2)
D256 = int(D128 / 2)
D512 = int(D256 / 2)
D1024 = int(D512 / 2) # set this to a number with many factors, like 210. According to http://homes.sice.indiana.edu/donbyrd/CMNExtremes.htm this is the real world limit.
if not int(D1024) == D1024:
logger.error(f"Warning: Lowest duration D0124 has decimal places: {D1024} but should be a plain integer. Your D4 value: {D4} has not enough 2^n factors. ")
D2 = D4 *2
D1 = D2 *2
DB = D1 * 2 #Breve
DL = DB * 2 #Longa
DM = DL * 2 #Maxima
if not int(D128) == D128:
raise ValueError(f"Durations must be integers (or .0). Yours: {D128}")
D_BASE_DURATIONS = (D1024, D512, D256, D64, D32, D16, D8, D4, D2, D1, DB, DL, DM)
#Duration Keywords
D_DEFAULT = 0
D_STACCATO = 1
D_TENUTO = 2
D_TIE = 3
def _baseDurationToTraditionalNumber(baseDuration):
"""4 = Quarter, 8 = Eighth, 0 = Brevis, -1= Longa
Created in the loop below on startup"""
if baseDuration == D4:
return 4
elif baseDuration == D8:
return 8
elif baseDuration == D16:
return 16
elif baseDuration == D2:
return 2
elif baseDuration == D1:
return 1
elif baseDuration == DB:
return 0
elif baseDuration == DL:
return -1
elif baseDuration == DM:
return -2
elif baseDuration == D32:
return 32
elif baseDuration == D64:
return 64
elif baseDuration == D128:
return 128
elif baseDuration == D256:
return 256
elif baseDuration == D512:
return 512
elif baseDuration == D1024:
return 1024
elif baseDuration == 0: #for KeySignatures and chords on init etc.
return 0
else:
raise ValueError("baseDuration does not match any traditioanl note duration value")
baseDurations = (0, D1024, D512, D256, D128, D64, D32, D16, D8, D4, D2, D1, DB, DL, DM) #from constants.py
baseDurationToTraditionalNumber = {}
for baseDuration in baseDurations:
baseDurationToTraditionalNumber[baseDuration] = _baseDurationToTraditionalNumber(baseDuration)
traditionalNumberToBaseDuration = {}
for baseDuration in baseDurations:
traditionalNumberToBaseDuration[_baseDurationToTraditionalNumber(baseDuration)] = baseDuration
def jackBBTicksToDuration(beatTypeAsTraditionalNumber, jackTicks, jackBeatTicks):
if None in (beatTypeAsTraditionalNumber, jackTicks, jackBeatTicks):
return None
else:
beatTypeDuration = traditionalNumberToBaseDuration[beatTypeAsTraditionalNumber]
#print (beatTypeAsTraditionalNumber, beatTypeDuration, jackTicks, jackBeatTicks)
factor = beatTypeDuration / jackBeatTicks
return jackTicks * factor