211 lines
8.4 KiB
Python
211 lines
8.4 KiB
Python
import crepe
|
|
from scipy.io import wavfile
|
|
import json
|
|
import csv
|
|
import numpy as np
|
|
|
|
|
|
# Define file paths
|
|
fileName = "NujabesFeather4stems/other.wav"
|
|
audio_file = "output/"+fileName
|
|
# Replace the slash with nothing to flatten the path
|
|
flat_name = fileName.replace("/", "")
|
|
# Remove the .wav extension
|
|
without_extension = flat_name[:-4] # removes last 4 characters (.wav)
|
|
# Create the output filename
|
|
output_csv = "crepe_output" + without_extension + ".csv"
|
|
|
|
def getNotesFromFreq(freqNotesArray, freqNotesConfidence):
|
|
notes_json='''{
|
|
"notes": [
|
|
{"note": "A", "octave": 0, "frequency": 27.5},
|
|
{"note": "Bb", "octave": 0, "frequency": 29.135},
|
|
{"note": "B", "octave": 0, "frequency": 30.868},
|
|
|
|
{"note": "C", "octave": 1, "frequency": 32.703},
|
|
{"note": "Db", "octave": 1, "frequency": 34.648},
|
|
{"note": "D", "octave": 1, "frequency": 36.708},
|
|
{"note": "Eb", "octave": 1, "frequency": 38.891},
|
|
{"note": "E", "octave": 1, "frequency": 41.203},
|
|
{"note": "F", "octave": 1, "frequency": 43.654},
|
|
{"note": "Gb", "octave": 1, "frequency": 46.249},
|
|
{"note": "G", "octave": 1, "frequency": 48.999},
|
|
{"note": "Ab", "octave": 1, "frequency": 51.913},
|
|
{"note": "A", "octave": 1, "frequency": 55.0},
|
|
{"note": "Bb", "octave": 1, "frequency": 58.27},
|
|
{"note": "B", "octave": 1, "frequency": 61.735},
|
|
|
|
{"note": "C", "octave": 2, "frequency": 65.406},
|
|
{"note": "Db", "octave": 2, "frequency": 69.296},
|
|
{"note": "D", "octave": 2, "frequency": 73.416},
|
|
{"note": "Eb", "octave": 2, "frequency": 77.782},
|
|
{"note": "E", "octave": 2, "frequency": 82.407},
|
|
{"note": "F", "octave": 2, "frequency": 87.307},
|
|
{"note": "Gb", "octave": 2, "frequency": 92.499},
|
|
{"note": "G", "octave": 2, "frequency": 97.999},
|
|
{"note": "Ab", "octave": 2, "frequency": 103.826},
|
|
{"note": "A", "octave": 2, "frequency": 110.0},
|
|
{"note": "Bb", "octave": 2, "frequency": 116.541},
|
|
{"note": "B", "octave": 2, "frequency": 123.471},
|
|
|
|
{"note": "C", "octave": 3, "frequency": 130.813},
|
|
{"note": "Db", "octave": 3, "frequency": 138.591},
|
|
{"note": "D", "octave": 3, "frequency": 146.832},
|
|
{"note": "Eb", "octave": 3, "frequency": 155.563},
|
|
{"note": "E", "octave": 3, "frequency": 164.814},
|
|
{"note": "F", "octave": 3, "frequency": 174.614},
|
|
{"note": "Gb", "octave": 3, "frequency": 184.997},
|
|
{"note": "G", "octave": 3, "frequency": 195.998},
|
|
{"note": "Ab", "octave": 3, "frequency": 207.652},
|
|
{"note": "A", "octave": 3, "frequency": 220.0},
|
|
{"note": "Bb", "octave": 3, "frequency": 233.082},
|
|
{"note": "B", "octave": 3, "frequency": 246.942},
|
|
|
|
{"note": "C", "octave": 4, "frequency": 261.626},
|
|
{"note": "Db", "octave": 4, "frequency": 277.183},
|
|
{"note": "D", "octave": 4, "frequency": 293.665},
|
|
{"note": "Eb", "octave": 4, "frequency": 311.127},
|
|
{"note": "E", "octave": 4, "frequency": 329.628},
|
|
{"note": "F", "octave": 4, "frequency": 349.228},
|
|
{"note": "Gb", "octave": 4, "frequency": 369.994},
|
|
{"note": "G", "octave": 4, "frequency": 391.995},
|
|
{"note": "Ab", "octave": 4, "frequency": 415.305},
|
|
{"note": "A", "octave": 4, "frequency": 440.0},
|
|
{"note": "Bb", "octave": 4, "frequency": 466.164},
|
|
{"note": "B", "octave": 4, "frequency": 493.883},
|
|
|
|
{"note": "C", "octave": 5, "frequency": 523.251},
|
|
{"note": "Db", "octave": 5, "frequency": 554.365},
|
|
{"note": "D", "octave": 5, "frequency": 587.33},
|
|
{"note": "Eb", "octave": 5, "frequency": 622.254},
|
|
{"note": "E", "octave": 5, "frequency": 659.255},
|
|
{"note": "F", "octave": 5, "frequency": 698.456},
|
|
{"note": "Gb", "octave": 5, "frequency": 739.989},
|
|
{"note": "G", "octave": 5, "frequency": 783.991},
|
|
{"note": "Ab", "octave": 5, "frequency": 830.609},
|
|
{"note": "A", "octave": 5, "frequency": 880.0},
|
|
{"note": "Bb", "octave": 5, "frequency": 932.328},
|
|
{"note": "B", "octave": 5, "frequency": 987.767},
|
|
|
|
{"note": "C", "octave": 6, "frequency": 1046.502},
|
|
{"note": "Db", "octave": 6, "frequency": 1108.731},
|
|
{"note": "D", "octave": 6, "frequency": 1174.659},
|
|
{"note": "Eb", "octave": 6, "frequency": 1244.508},
|
|
{"note": "E", "octave": 6, "frequency": 1318.51},
|
|
{"note": "F", "octave": 6, "frequency": 1396.913},
|
|
{"note": "Gb", "octave": 6, "frequency": 1479.978},
|
|
{"note": "G", "octave": 6, "frequency": 1567.982},
|
|
{"note": "Ab", "octave": 6, "frequency": 1661.219},
|
|
{"note": "A", "octave": 6, "frequency": 1760.0},
|
|
{"note": "Bb", "octave": 6, "frequency": 1864.655},
|
|
{"note": "B", "octave": 6, "frequency": 1975.533},
|
|
|
|
{"note": "C", "octave": 7, "frequency": 2093.005},
|
|
{"note": "Db", "octave": 7, "frequency": 2217.461},
|
|
{"note": "D", "octave": 7, "frequency": 2349.318},
|
|
{"note": "Eb", "octave": 7, "frequency": 2489.016},
|
|
{"note": "E", "octave": 7, "frequency": 2637.021},
|
|
{"note": "F", "octave": 7, "frequency": 2793.826},
|
|
{"note": "Gb", "octave": 7, "frequency": 2959.955},
|
|
{"note": "G", "octave": 7, "frequency": 3135.964},
|
|
{"note": "Ab", "octave": 7, "frequency": 3322.438},
|
|
{"note": "A", "octave": 7, "frequency": 3520.0},
|
|
{"note": "Bb", "octave": 7, "frequency": 3729.31},
|
|
{"note": "B", "octave": 7, "frequency": 3951.066},
|
|
|
|
{"note": "C", "octave": 8, "frequency": 4186.009}
|
|
]
|
|
}'''
|
|
notes_data = json.loads(notes_json)
|
|
finalNoteArray = []
|
|
|
|
for i, freq in enumerate(freqNotesArray):
|
|
bestFreqDif = float('inf')
|
|
if freqNotesConfidence[i] < 0.5:
|
|
finalNote = "NoNoteFound"
|
|
else :
|
|
for note_data in notes_data['notes']:
|
|
freqDif = abs(note_data['frequency'] - freq)
|
|
if freqDif < bestFreqDif:
|
|
bestFreqDif = freqDif
|
|
finalNote = note_data['note']
|
|
finalNoteArray.append(finalNote)
|
|
|
|
|
|
return finalNoteArray
|
|
|
|
|
|
|
|
|
|
try:
|
|
# Try to read existing CSV
|
|
with open(output_csv, newline='') as csvfile:
|
|
reader = csv.DictReader(csvfile)
|
|
data = list(reader)
|
|
|
|
# Extract frequency and confidence from CSV
|
|
time = [float(row['time']) for row in data]
|
|
frequency = [float(row['frequency']) for row in data]
|
|
confidence = [float(row['confidence']) for row in data]
|
|
|
|
print(f"Loaded {len(frequency)} data points from existing CSV")
|
|
|
|
except (FileNotFoundError, KeyError) as e:
|
|
# If file doesn't exist or has incorrect format, process the audio
|
|
print(f"Processing audio file: {audio_file}")
|
|
|
|
# Read audio file
|
|
sr, audio = wavfile.read(audio_file)
|
|
|
|
# Ensure audio is mono (if stereo, take first channel)
|
|
if len(audio.shape) > 1 and audio.shape[1] > 1:
|
|
audio = audio[:, 0]
|
|
|
|
# Convert audio to float32 if needed
|
|
if audio.dtype != np.float32:
|
|
# Normalize based on data type
|
|
if audio.dtype == np.int16:
|
|
audio = audio.astype(np.float32) / 32768.0
|
|
elif audio.dtype == np.int32:
|
|
audio = audio.astype(np.float32) / 2147483648.0
|
|
|
|
# Run CREPE pitch detection
|
|
time, frequency, confidence, activation = crepe.predict(audio, sr, viterbi=True)
|
|
|
|
# Write results to CSV
|
|
with open(output_csv, 'w', newline='') as csvfile:
|
|
fieldnames = ['time', 'frequency', 'confidence']
|
|
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
|
|
|
|
writer.writeheader()
|
|
for i,ArrayCombined in enumerate(zip(time, frequency, confidence)):
|
|
if confidence[i] >= 0.5:
|
|
writer.writerow({
|
|
'time': ArrayCombined[0],
|
|
'frequency': ArrayCombined[1],
|
|
'confidence': ArrayCombined[2]
|
|
})
|
|
|
|
print(f"Saved {len(frequency)} data points to {output_csv}")
|
|
|
|
# Convert frequencies to notes
|
|
notes = getNotesFromFreq(frequency, confidence)
|
|
|
|
# Save notes to another CSV file
|
|
notes_csv = "notes_output.csv"
|
|
with open(notes_csv, 'w', newline='') as csvfile:
|
|
fieldnames = ['time', 'frequency', 'confidence', 'note']
|
|
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
|
|
|
|
writer.writeheader()
|
|
for i,ArrayCombined in enumerate(zip(time, frequency, confidence, notes)):
|
|
if confidence[i] >= 0.5:
|
|
writer.writerow({
|
|
'time': ArrayCombined[0],
|
|
'frequency': ArrayCombined[1],
|
|
'confidence': ArrayCombined[2],
|
|
'note': ArrayCombined[3]
|
|
})
|
|
print(frequency[:30])
|
|
print(f"Saved {len(notes)} notes to {notes_csv}")
|
|
print(f"Sample of notes: {notes[:10]}") |