[fix] Better bpm
This commit is contained in:
parent
6ae754e893
commit
73f0765519
47
redilysis.py
47
redilysis.py
@ -38,8 +38,12 @@ _BPM_MIN=10
|
|||||||
_BPM_MAX=400
|
_BPM_MAX=400
|
||||||
|
|
||||||
# Argument parsing
|
# Argument parsing
|
||||||
# Audio Args
|
|
||||||
parser = argparse.ArgumentParser(prog='realtime_redis')
|
parser = argparse.ArgumentParser(prog='realtime_redis')
|
||||||
|
# Standard Args
|
||||||
|
parser.add_argument("-v","--verbose",action="store_true",help="Verbose")
|
||||||
|
# Redis Args
|
||||||
|
parser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str)
|
||||||
|
parser.add_argument("-p","--port",help="Port of the Redis server ",default="6379",type=str)
|
||||||
# Audio Capture Args
|
# Audio Capture Args
|
||||||
parser.add_argument('--list-devices','-L', action='store_true', help='Which devices are detected by pyaudio')
|
parser.add_argument('--list-devices','-L', action='store_true', help='Which devices are detected by pyaudio')
|
||||||
parser.add_argument('--mode','-m', required=False, default='spectrum', choices=['spectrum', 'bpm'], type=str, help='Which mode to use. Default=spectrum')
|
parser.add_argument('--mode','-m', required=False, default='spectrum', choices=['spectrum', 'bpm'], type=str, help='Which mode to use. Default=spectrum')
|
||||||
@ -47,16 +51,11 @@ parser.add_argument('--device','-d', required=False, type=int, help='Which pyaud
|
|||||||
parser.add_argument('--sampling-frequency','-s', required=False, default=0.1, type=float, help='Which frequency, in seconds. Default={}f '.format(_SAMPLING_FREQUENCY))
|
parser.add_argument('--sampling-frequency','-s', required=False, default=0.1, type=float, help='Which frequency, in seconds. Default={}f '.format(_SAMPLING_FREQUENCY))
|
||||||
parser.add_argument('--channels','-c', required=False, default=_CHANNELS, type=int, help='How many channels. Default={} '.format(_CHANNELS))
|
parser.add_argument('--channels','-c', required=False, default=_CHANNELS, type=int, help='How many channels. Default={} '.format(_CHANNELS))
|
||||||
parser.add_argument('--rate','-r', required=False, default=44100, type=int, help='The audio capture rate in Hz. Default={} '.format(_RATE))
|
parser.add_argument('--rate','-r', required=False, default=44100, type=int, help='The audio capture rate in Hz. Default={} '.format(_RATE))
|
||||||
#parser.add_argument('--frames','-f', required=False, default=4410, type=int, help='How many frames per buffer. Default={}'.format(_FRAMES_PER_BUFFER))
|
parser.add_argument('--frames','-f', required=False, default=4410, type=int, help='How many frames per buffer. Default={}'.format(_FRAMES_PER_BUFFER))
|
||||||
# BPM Mode Args
|
# BPM Mode Args
|
||||||
parser.add_argument('--bpm-min', required=False, default=_BPM_MIN, type=int, help='BPM mode only. The low BPM threshold. Default={} '.format(_BPM_MIN))
|
parser.add_argument('--bpm-min', required=False, default=_BPM_MIN, type=int, help='BPM mode only. The low BPM threshold. Default={} '.format(_BPM_MIN))
|
||||||
parser.add_argument('--bpm-max', required=False, default=_BPM_MAX, type=int, help='BPM mode only. The high BPM threshold. Default={} '.format(_BPM_MAX))
|
parser.add_argument('--bpm-max', required=False, default=_BPM_MAX, type=int, help='BPM mode only. The high BPM threshold. Default={} '.format(_BPM_MAX))
|
||||||
|
|
||||||
# Redis Args
|
|
||||||
parser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str)
|
|
||||||
parser.add_argument("-p","--port",help="Port of the Redis server ",default="6379",type=str)
|
|
||||||
# Standard Args
|
|
||||||
parser.add_argument("-v","--verbose",action="store_true",help="Verbose")
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# global
|
# global
|
||||||
@ -110,7 +109,6 @@ if( LIST_DEVICES ):
|
|||||||
list_devices()
|
list_devices()
|
||||||
os._exit(1)
|
os._exit(1)
|
||||||
|
|
||||||
p = pyaudio.PyAudio()
|
|
||||||
|
|
||||||
|
|
||||||
def m_bpm(audio_data):
|
def m_bpm(audio_data):
|
||||||
@ -122,7 +120,6 @@ def m_bpm(audio_data):
|
|||||||
global bpm
|
global bpm
|
||||||
global start
|
global start
|
||||||
|
|
||||||
bpm_delay = SAMPLING_FREQUENCY + start - time.time()
|
|
||||||
|
|
||||||
# Detect tempo / bpm
|
# Detect tempo / bpm
|
||||||
new_bpm, beats = librosa.beat.beat_track(
|
new_bpm, beats = librosa.beat.beat_track(
|
||||||
@ -138,19 +135,25 @@ def m_bpm(audio_data):
|
|||||||
'''
|
'''
|
||||||
# Correct the eventual octave error
|
# Correct the eventual octave error
|
||||||
if new_bpm < bpm_min or new_bpm > bpm_max:
|
if new_bpm < bpm_min or new_bpm > bpm_max:
|
||||||
|
found = False
|
||||||
octaveErrorList = [ 0.5, 2, 0.3333, 3 ]
|
octaveErrorList = [ 0.5, 2, 0.3333, 3 ]
|
||||||
for key,factor in enumerate(octaveErrorList):
|
for key,factor in enumerate(octaveErrorList):
|
||||||
correction = new_bpm * factor
|
correction = new_bpm * factor
|
||||||
if correction > bpm_min and correction < bpm_max:
|
if correction > bpm_min and correction < bpm_max:
|
||||||
debug( "Corrected bpm to:{}".format(correction))
|
debug( "Corrected high/low bpm:{} to:{}".format(new_bpm, correction))
|
||||||
new_bpm = correction
|
new_bpm = correction
|
||||||
|
found = True
|
||||||
break
|
break
|
||||||
|
if found == False:
|
||||||
if new_bpm < bpm_min :
|
if new_bpm < bpm_min :
|
||||||
new_bpm = bpm_min
|
new_bpm = bpm_min
|
||||||
else :
|
else :
|
||||||
new_bpm = bpm_max
|
new_bpm = bpm_max
|
||||||
|
|
||||||
|
debug("new_bpm:{}".format(new_bpm))
|
||||||
'''
|
'''
|
||||||
|
How to guess the next beats based on the data sent to redis
|
||||||
|
~~ A Dirty Graph ~~
|
||||||
|
|
||||||
|start end|
|
|start end|
|
||||||
Capture |........................|
|
Capture |........................|
|
||||||
@ -167,22 +170,29 @@ def m_bpm(audio_data):
|
|||||||
. passed (...b....b....b.)
|
. passed (...b....b....b.)
|
||||||
. guessed (..b....b....b....b...
|
. guessed (..b....b....b....b...
|
||||||
Next Beat Calculation b....b....b....b.|..b
|
Next Beat Calculation b....b....b....b.|..b
|
||||||
|
Beats |last beat
|
||||||
|
0 1 2 3 4
|
||||||
|
|
||||||
=> (Delay - last beat) + x*BPM/60 (with x >= read_delay/BPM/60)
|
|
||||||
Redis:
|
Redis:
|
||||||
bpm_sample_interval
|
|
||||||
|........................|
|
key bpm_sample_interval
|
||||||
bpm_delay
|
visual |........................|
|
||||||
|.........................|
|
|
||||||
|
key bpm_delay
|
||||||
|
visual |.........................|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
bpm = new_bpm
|
bpm = new_bpm
|
||||||
|
bpm_sample_interval = SAMPLING_FREQUENCY * 1000
|
||||||
|
bpm_delay = (SAMPLING_FREQUENCY + time.time() - start ) * 1000
|
||||||
|
pexpireat = int( 2 * bpm_sample_interval);
|
||||||
# Save to Redis
|
# Save to Redis
|
||||||
r.set( 'bpm', new_bpm, px=( 2* int(SAMPLING_FREQUENCY * 1000)))
|
r.set( 'bpm', round(bpm,2), px = pexpireat )
|
||||||
r.set( 'bpm_sample_interval', SAMPLING_FREQUENCY )
|
r.set( 'bpm_sample_interval', bpm_sample_interval )
|
||||||
r.set( 'bpm_delay', bpm_delay )
|
r.set( 'bpm_delay', bpm_delay )
|
||||||
r.set( 'beats', json.dumps( beats.tolist() ) )
|
r.set( 'beats', json.dumps( beats.tolist() ) )
|
||||||
debug( "bpm:{} bpm_delay:{} beats:{}".format(bpm,bpm_delay,beats) )
|
#debug( "pexpireat:{}".format(pexpireat))
|
||||||
|
debug( "bpm:{} bpm_delay:{} bpm_sample_interval:{} beats:{}".format(bpm,bpm_delay,bpm_sample_interval,beats) )
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def m_spectrum(audio_data):
|
def m_spectrum(audio_data):
|
||||||
@ -250,6 +260,7 @@ if MODE == 'spectrum':
|
|||||||
elif MODE == 'bpm':
|
elif MODE == 'bpm':
|
||||||
debug("In this mode, we will set keys: onset, bpm, beats")
|
debug("In this mode, we will set keys: onset, bpm, beats")
|
||||||
|
|
||||||
|
p = pyaudio.PyAudio()
|
||||||
stream = p.open(format=pyaudio.paFloat32,
|
stream = p.open(format=pyaudio.paFloat32,
|
||||||
channels=CHANNELS,
|
channels=CHANNELS,
|
||||||
rate=RATE,
|
rate=RATE,
|
||||||
|
Loading…
Reference in New Issue
Block a user