diff --git a/chart-wizard/.gitignore b/chart-wizard/.gitignore new file mode 100644 --- /dev/null +++ b/chart-wizard/.gitignore @@ -0,0 +1,2 @@ +.build/ +bin/ diff --git a/chart-wizard/Package.swift b/chart-wizard/Package.swift new file mode 100644 --- /dev/null +++ b/chart-wizard/Package.swift @@ -0,0 +1,14 @@ +// swift-tools-version:5.9 +import PackageDescription + +let package = Package( + name: "ChartWizard", + platforms: [.macOS(.v12)], + targets: [ + .executableTarget( + name: "ChartWizard", + path: "Sources/ChartWizard", + resources: [.copy("Assets")] + ), + ] +) diff --git a/chart-wizard/Sources/ChartWizard/AppDelegate.swift b/chart-wizard/Sources/ChartWizard/AppDelegate.swift new file mode 100644 --- /dev/null +++ b/chart-wizard/Sources/ChartWizard/AppDelegate.swift @@ -0,0 +1,45 @@ +import AppKit + +final class ChartWizardAppDelegate: NSObject, NSApplicationDelegate { + var wizard: WizardController? + + func applicationDidFinishLaunching(_ notification: Notification) { + let args = CommandLine.arguments + let path = args.count >= 2 ? args[1] : defaultLane() + do { + let model = try ChartModel(wizardJSON: URL(fileURLWithPath: path)) + let w = WizardController(model: model) + wizard = w + w.showWindow(nil) + NSApp.activate(ignoringOtherApps: true) + } catch { + let a = NSAlert() + a.messageText = "ChartWizard could not open that chart" + a.informativeText = """ + \(error.localizedDescription) + + Expecting a lane's vox4/.wizard.json — build one with + pop/.venv/bin/python pop//bin/wizard.py + """ + a.runModal() + NSApp.terminate(nil) + } + } + + /// With no argument, open whichever lane most recently emitted one. + private func defaultLane() -> String { + let fm = FileManager.default + let pop = URL(fileURLWithPath: fm.currentDirectoryPath).appendingPathComponent("pop") + let lanes = (try? fm.contentsOfDirectory(at: pop, includingPropertiesForKeys: nil)) ?? [] + let charts = lanes.map { $0.appendingPathComponent("vox4/.wizard.json") } + .filter { fm.fileExists(atPath: $0.path) } + let newest = charts.max { + let a = (try? $0.resourceValues(forKeys: [.contentModificationDateKey]).contentModificationDate) ?? .distantPast + let b = (try? $1.resourceValues(forKeys: [.contentModificationDateKey]).contentModificationDate) ?? .distantPast + return a < b + } + return newest?.path ?? pop.appendingPathComponent("loner/vox4/.wizard.json").path + } + + func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { true } +} diff --git a/chart-wizard/Sources/ChartWizard/ChartModel.swift b/chart-wizard/Sources/ChartWizard/ChartModel.swift new file mode 100644 --- /dev/null +++ b/chart-wizard/Sources/ChartWizard/ChartModel.swift @@ -0,0 +1,237 @@ +// ChartModel.swift — the chart, in memory, and the sidecar it writes back. +// +// Reads pop//vox4/.wizard.json (bin/wizard.py) and writes +// pop//chart-edits.json, which halo3.py merges over its CHART +// literal. The GUI never touches the Python: the CHART keeps the prose +// explaining every number, and this file keeps only numbers. +import Foundation + +struct Unit: Codable { + var t: String // the word or syllable as it is sung + var beat: Double // where the block sits on the grid + var dur: Double // how many beats it holds + var st: Double // her measured semitone, vs the lane tonic + var src0: Double // which piece of the take the block plays, + var src1: Double // in slice seconds + + // which CHART knob owns this block's left edge (halo3 emits it) + var pin: Int? // pre-split word index + var cut: CutKind? // nil = the word's own start; k = its k-th + // syllable cut; .auto = halo3 found it +} + +enum CutKind: Codable, Equatable { + case syllable(Int) + case auto + + init(from decoder: Decoder) throws { + let c = try decoder.singleValueContainer() + if let k = try? c.decode(Int.self) { self = .syllable(k) } + else { self = .auto } + } + func encode(to encoder: Encoder) throws { + var c = encoder.singleValueContainer() + switch self { + case .syllable(let k): try c.encode(k) + case .auto: try c.encode("auto") + } + } + var isDraggable: Bool { self != .auto } +} + +struct Event: Codable { + var a: Double + var b: Double + var kind: String // NOTE · FRIC · PUFF + var st: Double? +} + +struct Frames: Codable { + var st: [Double?] // semitones vs tonic, nil where unvoiced + var db: [Double] // level, dB below the take's peak + var hf: [Double] // share of energy above 3 kHz +} + +struct Phrase: Codable { + var slice: String + var wav: String + var sr: Int + var leadIn: Double + var beats: Double + var units: [Unit] + var events: [Event] + var frames: Frames +} + +struct ChartDoc: Codable { + var lane: String + var bpm: Double + var tonic: Double + var frame_s: Double + var phrases: [String: Phrase] +} + +// ── what a drag writes ──────────────────────────────────────────────── +// Only the four knobs the roll can move. Everything else in the CHART — +// the stretch caps, nohold, end — stays where its reasons are written. +struct PhraseEdits: Codable { + var times: [String: Double]? + var sylls: [String: [[SyllCut]]]? + var durs: [String: Double]? + var gaps: [String: Double]? +} + +// a syllable cut is [seconds-or-null, label] in the Python literal, so it +// has to survive a round trip through a heterogeneous JSON array. +enum SyllCut: Codable { + case time(Double) + case none + case label(String) + + init(from decoder: Decoder) throws { + let c = try decoder.singleValueContainer() + if c.decodeNil() { self = .none } + else if let d = try? c.decode(Double.self) { self = .time(d) } + else { self = .label(try c.decode(String.self)) } + } + func encode(to encoder: Encoder) throws { + var c = encoder.singleValueContainer() + switch self { + case .time(let d): try c.encode(d) + case .none: try c.encodeNil() + case .label(let s): try c.encode(s) + } + } +} + +final class ChartModel { + let doc: ChartDoc + let laneDir: URL + private(set) var name: String + private(set) var units: [Unit] + private(set) var dirty = false + + var phrase: Phrase { doc.phrases[name]! } + var bpm: Double { doc.bpm } + var secondsPerBeat: Double { 60.0 / doc.bpm } + + init(wizardJSON: URL) throws { + let data = try Data(contentsOf: wizardJSON) + doc = try JSONDecoder().decode(ChartDoc.self, from: data) + // …/pop//vox4/.wizard.json → …/pop/ + laneDir = wizardJSON.deletingLastPathComponent().deletingLastPathComponent() + guard let first = doc.phrases.keys.sorted().first else { + throw NSError(domain: "ChartWizard", code: 1, userInfo: [ + NSLocalizedDescriptionKey: "no phrases in \(wizardJSON.lastPathComponent)"]) + } + name = first + units = doc.phrases[first]!.units + } + + func select(phrase p: String) { + guard let ph = doc.phrases[p] else { return } + name = p + units = ph.units + } + + // ── the two drags ──────────────────────────────────────────────── + // A block's LEFT EDGE is where her word begins in the take. Moving it + // moves the previous block's end with it — the warp is one sequential + // frame map, so units cannot overlap and cannot leave a hole. + func moveBoundary(_ i: Int, toSource t: Double) { + guard i > 0, i < units.count, units[i].cut?.isDraggable ?? true else { return } + let lo = units[i - 1].src0 + 0.040 // never starve a neighbour + let hi = units[i].src1 - 0.040 + let t = min(max(t, lo), hi) + units[i].src0 = t + units[i - 1].src1 = t + dirty = true + } + + // A block's POSITION on the grid. Moving it right takes beats from the + // rest before it and gives them back to the rest after, so everything + // downstream keeps the bar it already has — which is how this chart has + // been tuned by hand all along. + func moveBlock(_ i: Int, toBeat b: Double) { + guard i >= 0, i < units.count else { return } + let lo = i > 0 ? units[i - 1].beat + units[i - 1].dur : 0 + let hi = i + 1 < units.count ? units[i + 1].beat - units[i].dur : doc.phrases[name]!.beats - units[i].dur + units[i].beat = min(max(b, lo), max(lo, hi)) + dirty = true + } + + // A block's RIGHT EDGE is how long it holds — the beats it is warped + // into, not how much audio it owns. + func resizeBlock(_ i: Int, toDur d: Double) { + guard i >= 0, i < units.count else { return } + let hi = i + 1 < units.count ? units[i + 1].beat - units[i].beat : doc.phrases[name]!.beats - units[i].beat + units[i].dur = min(max(d, 0.25), max(0.25, hi)) + dirty = true + } + + func revert() { + units = doc.phrases[name]!.units + dirty = false + } + + // ── the sidecar ────────────────────────────────────────────────── + var editsURL: URL { laneDir.appendingPathComponent("chart-edits.json") } + + /// Only what actually moved. A block left alone writes nothing, so the + /// sidecar stays a short list of this session's decisions rather than a + /// second copy of the chart. + func edits() -> PhraseEdits { + let original = doc.phrases[name]!.units + var times: [String: Double] = [:] + var sylls: [String: [[SyllCut]]] = [:] + var durs: [String: Double] = [:] + var gaps: [String: Double] = [:] + + for (i, u) in units.enumerated() where i < original.count { + let o = original[i] + if abs(u.src0 - o.src0) > 1e-4, let pin = u.pin { + switch u.cut { + case nil: + times["\(pin)"] = round(u.src0 * 1000) / 1000 + case .syllable: + // one word's cuts are one list, so rebuild the whole + // list from every unit sharing this pin. + let family = units.filter { $0.pin == pin } + .sorted { $0.src0 < $1.src0 } + sylls["\(pin)"] = [family.enumerated().map { (k, f) -> [SyllCut] in + k == 0 ? [.none, .label(f.t)] + : [.time(round(f.src0 * 1000) / 1000), .label(f.t)] + }].flatMap { $0 } + case .auto: + break + } + } + if abs(u.dur - o.dur) > 1e-4 { durs["\(i)"] = round(u.dur * 100) / 100 } + // a block's grid position is the rest in front of it + let prevEnd = i > 0 ? units[i - 1].beat + units[i - 1].dur : 0 + let origPrevEnd = i > 0 ? original[i - 1].beat + original[i - 1].dur : 0 + let gap = u.beat - prevEnd, origGap = o.beat - origPrevEnd + if i > 0, abs(gap - origGap) > 1e-4 { + gaps["\(i - 1)"] = round(gap * 100) / 100 + } + } + return PhraseEdits(times: times.isEmpty ? nil : times, + sylls: sylls.isEmpty ? nil : sylls, + durs: durs.isEmpty ? nil : durs, + gaps: gaps.isEmpty ? nil : gaps) + } + + /// Merge into whatever is already on disk — another phrase's edits from + /// an earlier session must survive saving this one. + func save() throws { + var all: [String: PhraseEdits] = [:] + if let data = try? Data(contentsOf: editsURL) { + all = (try? JSONDecoder().decode([String: PhraseEdits].self, from: data)) ?? [:] + } + all[name] = edits() + let enc = JSONEncoder() + enc.outputFormatting = [.prettyPrinted, .sortedKeys] + try enc.encode(all).write(to: editsURL) + dirty = false + } +} diff --git a/chart-wizard/Sources/ChartWizard/RollView.swift b/chart-wizard/Sources/ChartWizard/RollView.swift new file mode 100644 --- /dev/null +++ b/chart-wizard/Sources/ChartWizard/RollView.swift @@ -0,0 +1,253 @@ +// RollView.swift — the chart, as something you can grab. +// +// Two clocks are on screen at once, which is the whole reason this is +// hard to do in a text editor. Horizontally the roll is the BEAT GRID — +// where each word lands in the bar. Inside every block, drawn to that +// block's own width, is the piece of the take it plays, in SOURCE +// seconds. Dragging the block moves it in the first clock; dragging its +// edge moves it in the second. Melodyne's arrangement, with her measured +// pitch on the vertical axis so a word sits at the note she sang. +// +// drag a block move it on the grid (steals from the rest +// in front, gives it back to the one behind, +// so nothing downstream moves) +// drag its LEFT edge move the boundary in her voice — the cut +// that decides which mouth belongs to which +// word. Snaps to measured event edges. +// drag its RIGHT edge how many beats it holds +// ⌥ while dragging no snapping +// click select · space plays from there +import AppKit + +protocol RollViewDelegate: AnyObject { + func rollDidEdit(_ view: RollView) + func rollDidSelect(_ view: RollView, unit: Int?) + func rollRequestsPlay(_ view: RollView, fromBeat: Double) +} + +final class RollView: NSView { + weak var delegate: RollViewDelegate? + var model: ChartModel? { didSet { needsDisplay = true } } + var playhead: Double? { didSet { needsDisplay = true } } // seconds + private(set) var selected: Int? + + private var pxPerBeat: CGFloat = 46 + private let topPad: CGFloat = 26 + private let lane: CGFloat = 15 // pixels per semitone + + // ── geometry ───────────────────────────────────────────────────── + private var stCenter: Double { + guard let m = model, !m.units.isEmpty else { return 4 } + let all = m.units.map { $0.st } + return (all.min()! + all.max()!) / 2 + } + private func x(beat: Double) -> CGFloat { CGFloat(beat) * pxPerBeat + 8 } + private func beat(x: CGFloat) -> Double { Double((x - 8) / pxPerBeat) } + private func y(st: Double) -> CGFloat { + bounds.midY + CGFloat(st - stCenter) * -lane + } + private func rect(_ u: Unit) -> NSRect { + NSRect(x: x(beat: u.beat), y: y(st: u.st) - 13, + width: max(6, CGFloat(u.dur) * pxPerBeat - 2), height: 26) + } + + override var isFlipped: Bool { false } + override var acceptsFirstResponder: Bool { true } + + override var intrinsicContentSize: NSSize { + guard let m = model else { return NSSize(width: 900, height: 380) } + return NSSize(width: CGFloat(m.phrase.beats + 2) * pxPerBeat + 16, height: 380) + } + + func zoom(by f: CGFloat) { + pxPerBeat = min(220, max(14, pxPerBeat * f)) + invalidateIntrinsicContentSize() + needsDisplay = true + } + + // ── drawing ────────────────────────────────────────────────────── + override func draw(_ dirtyRect: NSRect) { + NSColor(calibratedWhite: 0.08, alpha: 1).setFill() + dirtyRect.fill() + guard let m = model else { return } + let ph = m.phrase + + drawGrid(m) + for (i, u) in m.units.enumerated() { drawBlock(m, ph, u, index: i) } + drawPlayhead(m) + } + + private func drawGrid(_ m: ChartModel) { + let bars = Int((m.phrase.beats / 4).rounded(.up)) + for bar in 0...max(0, bars) { + let bx = x(beat: Double(bar * 4)) + NSColor(calibratedWhite: 0.30, alpha: 1).setFill() + NSRect(x: bx, y: 0, width: 1, height: bounds.height).fill() + let label = NSAttributedString(string: "\(bar)", attributes: [ + .font: NSFont.monospacedSystemFont(ofSize: 9, weight: .regular), + .foregroundColor: NSColor(calibratedWhite: 0.45, alpha: 1)]) + label.draw(at: NSPoint(x: bx + 3, y: bounds.height - topPad + 8)) + for b in 1..<4 { + let sx = x(beat: Double(bar * 4 + b)) + NSColor(calibratedWhite: 0.16, alpha: 1).setFill() + NSRect(x: sx, y: 0, width: 1, height: bounds.height).fill() + } + } + } + + // Her voice, drawn INSIDE the block at the block's width: peak per + // column over the source span. This is the part that makes a bad + // boundary visible — a word holding the next word's consonant shows + // it as a bright tail with nothing behind it. + private func drawBlock(_ m: ChartModel, _ ph: Phrase, _ u: Unit, index i: Int) { + let r = rect(u) + let isSel = (selected == i) + let body = isSel ? NSColor(calibratedRed: 0.98, green: 0.36, blue: 0.62, alpha: 0.22) + : NSColor(calibratedRed: 0.44, green: 0.62, blue: 0.98, alpha: 0.18) + body.setFill() + NSBezierPath(roundedRect: r, xRadius: 3, yRadius: 3).fill() + + let f0 = Int(u.src0 / m.doc.frame_s), f1 = Int(u.src1 / m.doc.frame_s) + let n = max(1, f1 - f0) + let cols = max(1, Int(r.width)) + NSColor(calibratedWhite: 0.92, alpha: 0.75).setFill() + for c in 0.. -60 else { continue } + let h = CGFloat((peak + 60) / 60) * (r.height * 0.44) + // a consonant is dim but BRIGHT — tint it so it can be seen + if bright > 0.5 { + NSColor(calibratedRed: 1.0, green: 0.85, blue: 0.35, alpha: 0.85).setFill() + } else { + NSColor(calibratedWhite: 0.92, alpha: 0.75).setFill() + } + NSRect(x: r.minX + CGFloat(c), y: r.midY - h, width: 1, height: h * 2).fill() + } + + (isSel ? NSColor(calibratedRed: 1, green: 0.45, blue: 0.7, alpha: 1) + : NSColor(calibratedWhite: 0.55, alpha: 1)).setStroke() + let p = NSBezierPath(roundedRect: r, xRadius: 3, yRadius: 3) + p.lineWidth = isSel ? 2 : 1 + p.stroke() + + // an edge no chart knob owns cannot be dragged — say so rather + // than letting a drag silently do nothing + if u.cut == .auto { + NSColor(calibratedWhite: 0.35, alpha: 1).setFill() + NSRect(x: r.minX, y: r.minY, width: 2, height: r.height).fill() + } + + let text = NSAttributedString(string: u.t, attributes: [ + .font: NSFont.monospacedSystemFont(ofSize: 10, weight: .medium), + .foregroundColor: NSColor(calibratedWhite: isSel ? 1.0 : 0.80, alpha: 1)]) + text.draw(at: NSPoint(x: r.minX + 3, y: r.maxY + 1)) + } + + private func drawPlayhead(_ m: ChartModel) { + guard let t = playhead else { return } + let px = x(beat: t / m.secondsPerBeat) + NSColor(calibratedRed: 1, green: 0.9, blue: 0.3, alpha: 0.9).setFill() + NSRect(x: px, y: 0, width: 1.5, height: bounds.height).fill() + } + + // ── dragging ───────────────────────────────────────────────────── + private enum Grab { case body(Int, Double), leftEdge(Int), rightEdge(Int) } + private var grab: Grab? + + private func hit(_ p: NSPoint) -> Grab? { + guard let m = model else { return nil } + for (i, u) in m.units.enumerated().reversed() { + let r = rect(u).insetBy(dx: 0, dy: -4) + guard r.contains(p) else { continue } + if p.x - r.minX < 6 { return .leftEdge(i) } + if r.maxX - p.x < 6 { return .rightEdge(i) } + return .body(i, beat(x: p.x) - u.beat) + } + return nil + } + + override func resetCursorRects() { + guard let m = model else { return } + for u in m.units { + let r = rect(u) + addCursorRect(NSRect(x: r.minX - 3, y: r.minY, width: 8, height: r.height), + cursor: .resizeLeftRight) + addCursorRect(NSRect(x: r.maxX - 5, y: r.minY, width: 8, height: r.height), + cursor: .resizeLeftRight) + } + } + + override func mouseDown(with e: NSEvent) { + let p = convert(e.locationInWindow, from: nil) + grab = hit(p) + switch grab { + case .body(let i, _), .leftEdge(let i), .rightEdge(let i): + selected = i + case nil: + selected = nil + } + delegate?.rollDidSelect(self, unit: selected) + needsDisplay = true + } + + override func mouseDragged(with e: NSEvent) { + guard let m = model, let g = grab else { return } + let p = convert(e.locationInWindow, from: nil) + let free = e.modifierFlags.contains(.option) + switch g { + case .body(let i, let offset): + var b = beat(x: p.x) - offset + if !free { b = (b * 2).rounded() / 2 } // half-beat grid + m.moveBlock(i, toBeat: b) + case .rightEdge(let i): + var d = beat(x: p.x) - m.units[i].beat + if !free { d = (d * 2).rounded() / 2 } + m.resizeBlock(i, toDur: d) + case .leftEdge(let i): + guard i > 0 else { return } + // the left edge lives in HER clock, not the grid's: how far + // into the block the pointer is, scaled back to source seconds + let u = m.units[i] + let r = rect(u) + let frac = Double((p.x - r.minX) / max(1, r.width)) + var t = u.src0 + frac * (u.src1 - u.src0) + if !free { t = snapToEvent(m, t) } + m.moveBoundary(i, toSource: t) + } + delegate?.rollDidEdit(self) + needsDisplay = true + } + + override func mouseUp(with e: NSEvent) { grab = nil } + + /// The audio already told us where the edges are. Snap to the nearest + /// measured event edge within 40 ms so a drag lands on a real onset + /// rather than near one. + private func snapToEvent(_ m: ChartModel, _ t: Double) -> Double { + var best = t, bestD = 0.040 + for e in m.phrase.events { + for edge in [e.a, e.b] where abs(edge - t) < bestD { + bestD = abs(edge - t); best = edge + } + } + return best + } + + override func keyDown(with e: NSEvent) { + guard let m = model else { return super.keyDown(with: e) } + switch e.charactersIgnoringModifiers { + case " ": + let from = selected.map { m.units[$0].beat } ?? 0 + delegate?.rollRequestsPlay(self, fromBeat: from) + case "=", "+": zoom(by: 1.25) + case "-", "_": zoom(by: 0.8) + default: super.keyDown(with: e) + } + } +} diff --git a/chart-wizard/Sources/ChartWizard/WarpEngine.swift b/chart-wizard/Sources/ChartWizard/WarpEngine.swift new file mode 100644 --- /dev/null +++ b/chart-wizard/Sources/ChartWizard/WarpEngine.swift @@ -0,0 +1,198 @@ +// WarpEngine.swift — hear the drag immediately. +// +// The real render is halo3's: WORLD analysis, a frame-axis warp where +// vowels absorb the stretch and consonants ride near 1:1, the pitch snap, +// the halos. It takes half a minute and it is the thing that ships. This +// is not that. This is WSOLA on the raw slice — overlap-add with a +// correlation search so the grains line up — assembled onto the beat grid +// with a kick, in a few milliseconds, so a boundary can be judged by ear +// while the mouse is still down. Timing is what it has to be honest +// about, and timing is exactly what WSOLA preserves. +import AVFoundation + +final class WarpEngine { + private let engine = AVAudioEngine() + private let player = AVAudioPlayerNode() + private var source: [Float] = [] + private var sr: Double = 44100 + private(set) var isPlaying = false + private var startHostTime: AVAudioTime? + private var renderedFrames: AVAudioFrameCount = 0 + + init() { + engine.attach(player) + engine.connect(player, to: engine.mainMixerNode, + format: AVAudioFormat(standardFormatWithSampleRate: 44100, channels: 1)) + } + + func load(wav: URL) throws { + let file = try AVAudioFile(forReading: wav) + sr = file.processingFormat.sampleRate + guard let buf = AVAudioPCMBuffer(pcmFormat: file.processingFormat, + frameCapacity: AVAudioFrameCount(file.length)) else { return } + try file.read(into: buf) + let n = Int(buf.frameLength) + var mono = [Float](repeating: 0, count: n) + if let ch = buf.floatChannelData { + let chans = Int(buf.format.channelCount) + for i in 0.., toLength out: Int) -> [Float] { + let src = Array(x) + guard out > 0 else { return [] } + guard src.count > 8 else { return [Float](repeating: 0, count: out) } + let rate = Double(src.count) / Double(out) + if abs(rate - 1.0) < 0.01 && src.count >= out { return Array(src[0.. 0 { + // line the next grain up with the tail we just wrote + var bestScore = -Float.greatestFiniteMagnitude + let lo = max(0, Int(anaPos.rounded()) - search) + let hi = min(src.count - win - 1, Int(anaPos.rounded()) + search) + if lo <= hi { + for cand in stride(from: lo, through: hi, by: 2) { + var score: Float = 0 + for k in stride(from: 0, to: synHop, by: 2) { + score += prevTail[k] * src[cand + k] + } + if score > bestScore { bestScore = score; best = cand } + } + } + } + best = min(max(0, best), max(0, src.count - win - 1)) + for k in 0..= Double(src.count - win) { anaPos = Double(max(0, src.count - win - 1)) } + } + for i in 0.. 1e-6 { y[i] /= norm[i] } + return Array(y[0.. AVAudioPCMBuffer? { + let total = Int(((totalBeats + 2) * spb) * sr) + guard total > 0, + let fmt = AVAudioFormat(standardFormatWithSampleRate: sr, channels: 1), + let buf = AVAudioPCMBuffer(pcmFormat: fmt, frameCapacity: AVAudioFrameCount(total)) + else { return nil } + buf.frameLength = AVAudioFrameCount(total) + guard let out = buf.floatChannelData?[0] else { return nil } + for i in 0..= 0, b > a, b <= source.count else { continue } + let target = Int(u.dur * spb * sr) + guard target > 0 else { continue } + let warped = wsola(source[a..= 0, i < total else { continue } + var g: Float = 1 + if k < fade { g = 0.5 - 0.5 * cos(.pi * Float(k) / Float(fade)) } + else if k >= warped.count - fade { + g = 0.5 - 0.5 * cos(.pi * Float(warped.count - k) / Float(fade)) + } + out[i] += v * g + } + } + + if kick { + let beats = Int(totalBeats.rounded(.up)) + let len = Int(0.09 * sr) + for beat in 0...max(0, beats) { + let at = Int(Double(beat) * spb * sr) + for k in 0..= 0, i < total else { break } + let t = Double(k) / sr + let env = exp(-t * 38.0) + let f = 118.0 * exp(-t * 26.0) + 44.0 + out[i] += Float(sin(2 * .pi * f * t) * env * 0.30) + } + } + } + return buf + } + + /// Play from a beat by slicing the assembled buffer — scheduleBuffer + /// has no start offset, and copying a few hundred KB is free next to + /// re-warping every unit. + func play(_ buf: AVAudioPCMBuffer, fromBeat beat: Double = 0, spb: Double = 0.5) { + stop() + do { try engine.start() } catch { return } + let skip = Int(max(0, beat * spb * sr)) + guard skip < Int(buf.frameLength) else { return } + let piece: AVAudioPCMBuffer + if skip == 0 { + piece = buf + } else { + let n = AVAudioFrameCount(Int(buf.frameLength) - skip) + guard let cut = AVAudioPCMBuffer(pcmFormat: buf.format, frameCapacity: n), + let src = buf.floatChannelData?[0], let dst = cut.floatChannelData?[0] + else { return } + cut.frameLength = n + for i in 0../vox4/.wizard.json] +// +// The lane's chart is authored in Python (halo3.py's CHART) and rendered +// through WORLD and a C engine. Everything about that is right except the +// loop: a boundary is a float you type, and hearing it costs half a +// minute. This is the same chart with a handle on it — the blocks are the +// units halo3 will warp, the audio inside them is the take, and Render +// hands the edits back to the pipeline that ships. +import AppKit + +let app = NSApplication.shared +let delegate = ChartWizardAppDelegate() +app.delegate = delegate +app.setActivationPolicy(.regular) +app.run() diff --git a/pop/lib/nervox.py b/pop/lib/nervox.py new file mode 100644 --- /dev/null +++ b/pop/lib/nervox.py @@ -0,0 +1,148 @@ +"""nervox — make a regulated voice sound nervous again. + +@jeffrey, 2026-08-19, on the loner lane: "i think wavering notes too / +flanging and wiggling the pitches · would be nice · so the voice sounds +more nervous · lets call this 'nervox' technique · and canonize it in our +/pop tooling setup". + +THE PROBLEM IT SOLVES. Every WORLD lane here ends up snapping the singer +onto a grid — cult's sing.py, loner's halo3, factory's chart.py. The snap +is what makes her notes read as NOTES against a strict beat, and it is +also what makes her sound like a machine: a held tone whose f0 is a +straight line does not occur in a human throat. Turning the snap down +gets the humanity back by giving up the regulation, which is the wrong +trade. nervox keeps the regulation and puts the tremor back on top. + +TWO PARTS, and they are different instruments: + + waver() f0 modulation. NOT vibrato — vibrato is periodic and + confident. This is three incommensurate rates beating + against each other plus a smoothed random walk, so the pitch + never repeats its own wobble. That irregularity is the whole + effect; a single clean LFO reads as an opera singer, and + these read as someone whose voice is not quite steady. + + flange() a modulated short delay through the voice. Sweeping comb + notches make the timbre itself unstable, which is the part + you hear as nerves rather than as tuning. + +TWO RULES, both learned the hard way on loner: + + 1. Waver HELD notes only. A slide is already moving; wobbling it makes + mush. Pass `rate` (semitones/second, smoothed) and frames above + GLIDE_ST_S are left alone — the same test that decides where the + pitch snap lets go, so the two agree by construction. + 2. Ramp in. A tremor present at the attack sounds like a broken + sample; one that grows over ~120 ms sounds like a held note going + unsteady, which is what a nervous singer actually does. + +Deterministic: everything is seeded, so a render is reproducible and two +runs of the same score are byte-comparable. + + from nervox import waver, flange + f0 = waver(f0, frame_s, rate=rate) # cents of tremor on f0 + x = flange(x, fs) # comb sweep on the audio +""" + +import numpy as np + +# the same threshold the pitch snap uses to decide she is sliding +GLIDE_ST_S = 18.0 + +WAVER_CENTS = 22.0 # depth of the tremor, cents peak +WAVER_RATES = (4.3, 5.9, 7.1) # incommensurate, so the wobble never repeats +WAVER_DRIFT_HZ = 0.7 # how fast the random walk under it moves +WAVER_RAMP_S = 0.120 # a tremor at the attack reads as a broken sample + +FLANGE_MS = (0.6, 4.5) # sweep range of the delay +FLANGE_HZ = 0.23 # the sweep +FLANGE_DRIFT_HZ = 0.07 # …and a slower drift under it, so it never cycles +FLANGE_FB = 0.35 +FLANGE_MIX = 0.38 + + +def _walk(n, rng, hz, frame_s): + """A smoothed random walk in [-1, 1] — the part that will not repeat.""" + if n <= 0: + return np.zeros(0) + step = max(1, int(round(1.0 / max(hz, 1e-6) / frame_s))) + knots = rng.uniform(-1.0, 1.0, size=n // step + 2) + w = np.interp(np.arange(n), np.arange(len(knots)) * step, knots) + k = max(1, step // 2) + return np.convolve(w, np.ones(k) / k, mode="same") + + +def waver(f0, frame_s, rate=None, cents=WAVER_CENTS, seed=0x10AE, + voiced=None, ramp_s=WAVER_RAMP_S): + """Put an unsteady tremor on a corrected f0 contour. + + f0 Hz per frame, 0 where unvoiced + rate |df0/dt| in semitones/second per frame; frames above + GLIDE_ST_S are left alone (she is sliding, not holding) + """ + f0 = np.asarray(f0, dtype=float) + n = len(f0) + if n == 0: + return f0 + v = (f0 > 0) if voiced is None else np.asarray(voiced, dtype=bool)[:n] + rng = np.random.default_rng(seed) + t = np.arange(n) * frame_s + + # three rates beating, each with its own slowly wandering depth + trem = np.zeros(n) + for i, hz in enumerate(WAVER_RATES): + depth = 0.55 + 0.45 * _walk(n, rng, WAVER_DRIFT_HZ, frame_s) + trem += depth * np.sin(2 * np.pi * hz * t + rng.uniform(0, 2 * np.pi)) + trem /= len(WAVER_RATES) + trem = 0.75 * trem + 0.25 * _walk(n, rng, WAVER_DRIFT_HZ * 1.6, frame_s) + + # held notes only — a slide is already moving + hold = np.ones(n) + if rate is not None: + r = np.asarray(rate, dtype=float)[:n] + hold = np.clip(1.0 - (r - GLIDE_ST_S) / GLIDE_ST_S, 0.0, 1.0) + + # …and ramp in from each voiced onset + ramp = np.zeros(n) + k = max(1, int(round(ramp_s / frame_s))) + run = 0 + for i in range(n): + run = run + 1 if v[i] else 0 + ramp[i] = min(1.0, run / k) + + out = f0.copy() + out[v] = f0[v] * 2.0 ** ((cents * trem * hold * ramp)[v] / 1200.0) + return out + + +def flange(x, fs, depth_ms=FLANGE_MS, hz=FLANGE_HZ, fb=FLANGE_FB, + mix=FLANGE_MIX, seed=0x11AE): + """A modulated short delay — the timbre goes unstable, not the tuning.""" + x = np.asarray(x, dtype=float) + n = len(x) + if n == 0: + return x + t = np.arange(n) / float(fs) + lo, hi = depth_ms[0] / 1000.0, depth_ms[1] / 1000.0 + rng = np.random.default_rng(seed) + ph = rng.uniform(0, 2 * np.pi) + sweep = 0.5 - 0.5 * np.cos(2 * np.pi * hz * t + ph) + sweep = 0.78 * sweep + 0.22 * (0.5 - 0.5 * np.cos(2 * np.pi * FLANGE_DRIFT_HZ * t)) + d = (lo + (hi - lo) * sweep) * fs + + # linear-interpolated delay line with feedback, written in place so the + # feedback path hears its own output the way a real flanger does + y = np.zeros(n) + buf = np.zeros(n) + for i in range(n): + di = d[i] + j = i - di + if j < 1: + v = 0.0 + else: + j0 = int(j) + fr = j - j0 + v = buf[j0] * (1 - fr) + buf[j0 + 1] * fr if j0 + 1 < n else buf[j0] + buf[i] = x[i] + fb * v + y[i] = v + return (1.0 - mix) * x + mix * y diff --git a/pop/loner/.gitignore b/pop/loner/.gitignore --- a/pop/loner/.gitignore +++ b/pop/loner/.gitignore @@ -30,3 +30,10 @@ # The compiled C engine. c/lonerremix out/.segments/ vox4/.cache/ + +# The dub/take bank — bin/singdub.py rebuilds every warped line from +# samples/ (a translation) or samples/corpus/ (another take). Derived +# media, same rule as vox4/: 37 MB of it, and none of it is a source. +# The ElevenLabs mp3s beside them ARE kept — those came from a paid API +# call against her cloned voice and cannot be regenerated for free. +vox-dub/sung-*.wav diff --git a/pop/loner/bin/audit.py b/pop/loner/bin/audit.py --- a/pop/loner/bin/audit.py +++ b/pop/loner/bin/audit.py @@ -11,13 +11,36 @@ # made each word's span swallow the head of the next one — that is what # "for" containing "time" was. So the transcript is never the authority; # the audio is. # -# This finds the sung EVENTS with no reference to any transcript — voiced, -# loud runs, split wherever the pitch plateau moves — and then asks of -# every charted unit: which events fall inside your span, and how much of -# each? A unit holding more than one event is carrying a neighbour's -# word. A unit holding a fraction of one is clipping it. +# This finds the sung EVENTS with no reference to any transcript, and then +# asks of every charted unit: which events fall inside your span? +# +# THREE KINDS OF EVENT, because a word is not only its vowel. Splitting on +# pitch alone — which is all this did at first — cannot see a consonant: a +# fricative has no pitch, so the estimator hands back a garbage number and +# the /s/ of "self" merges into the vowel of "my". That read every CORRECT +# sibilant boundary in the take as contamination and buried the three real +# ones under sixteen flags. So each run is split where the pitch plateau +# moves OR where the brightness does, and classified: +# +# NOTE voiced, dark — a sung syllable +# FRIC bright above 3 kHz — /s/ /f/ /ʃ/, an onset or a coda +# PUFF unvoiced, dark — a breath, a stop closure, a burst +# +# and the rule is the singer's, not the transcript's: a consonant belongs +# to the note it LEADS INTO. A unit may open with a fricative — that is +# its own onset — and may end with one when nothing follows it closely, +# which is a coda. A unit that ends with a fricative belonging to the next +# unit's note is carrying the next word's mouth, which is the bug that had +# "stone" entering as "-tone". +# +# ZOOM: given a time window, it stops summarising and prints the frames — +# level, pitch and brightness, one line per 5 ms — which is the view every +# boundary in this take has actually been pinned from. A fricative is DIM +# but BRIGHT (fd31ffd10), a stop closure is dim and DARK, and a note change +# is a step in the pitch column; those three shapes are the whole method. # # pop/.venv/bin/python pop/loner/bin/audit.py [phrase] +# pop/.venv/bin/python pop/loner/bin/audit.py [phrase] import json, os, sys import numpy as np @@ -31,19 +54,56 @@ TONIC = 237.0 SPB = 60.0 / 122.0 GATE_DB = -34.0 # a run must clear this to be a sung event MIN_EVENT_S = 0.070 # shorter than this is a transient, not a syllable +MIN_NOTE_S = 0.150 # a real sung syllable here; below it, a glide +MIN_CONS_S = 0.070 # below this, a click rather than a consonant +HELD_FRAC = 0.25 # a unit HOLDS an event at this share of it… +HELD_S = 0.100 # …or at this many seconds of it, whichever first +COVERED = 0.75 # an event played below this share is partly lost PITCH_STEP = 0.7 # semitones of sustained change that split an event +BRIGHT_STEP = 0.45 # change in >3 kHz share that splits an event +BRIGHT = 0.50 # above this share of energy, the frame is a fricative +VOICED = 0.50 # below this fraction of pitched frames, it is unvoiced +ONSET_GAP_S = 0.200 # a fricative this close to the next note is its onset -def events(x, fs): - """Sung events, straight from the audio. No transcript involved.""" +def columns(x, fs): + """f0, level and brightness per frame — the three columns every boundary + in this take has been read from, and the only measurements here.""" f0r, t = pw.harvest(x, fs, f0_floor=70.0, f0_ceil=600.0, frame_period=FRAME_S * 1000) f0 = pw.stonemask(x, f0r, t, fs) n = int(round(fs * FRAME_S)) m = min(len(f0), len(x) // n) - rms = np.sqrt((x[:m * n].reshape(m, n) ** 2).mean(axis=1)) - gate = (np.max(np.abs(x)) or 1.0) * 10.0 ** (GATE_DB / 20.0) - on = rms > gate - st = np.where(f0[:m] > 0, 12.0 * np.log2(np.maximum(f0[:m], 1e-6) / TONIC), np.nan) + fr = x[:m * n].reshape(m, n) + rms = np.sqrt((fr ** 2).mean(axis=1)) + peak = np.max(np.abs(x)) or 1.0 + + # the share of frame energy above 3 kHz. /s/ and /f/ run over 0.9 at + # levels a pure level gate calls silence; a stop closure runs low in + # BOTH columns, which is how the two are told apart. + win = np.hanning(n) + mag = np.abs(np.fft.rfft(fr * win, axis=1)) ** 2 + fk = np.fft.rfftfreq(n, 1.0 / fs) + hi = mag[:, fk >= 3000.0].sum(axis=1) / np.maximum(mag.sum(axis=1), 1e-20) + + f0 = f0[:m] + st = np.where(f0 > 0, 12.0 * np.log2(np.maximum(f0, 1e-6) / TONIC), np.nan) + return f0, st, rms, hi, peak, m + + +def classify(st, hi, u, v): + """NOTE, FRIC or PUFF — and the pitch, when it has one.""" + voiced = st[u:v][~np.isnan(st[u:v])] + if float(np.median(hi[u:v])) >= BRIGHT: + return "FRIC", float("nan") + if len(voiced) < VOICED * (v - u): + return "PUFF", float("nan") + return "NOTE", float(np.median(voiced)) + + +def events(x, fs): + """Sung events, straight from the audio. No transcript involved.""" + f0, st, rms, hi, peak, m = columns(x, fs) + on = rms > peak * 10.0 ** (GATE_DB / 20.0) runs, k = [], 0 while k < m: @@ -57,28 +117,50 @@ k = j else: k += 1 - out = [] # split each run where the pitch plateau moves + out = [] # split each run where pitch OR brightness steps W = int(round(0.080 / FRAME_S)) for (a, b) in runs: cuts = [a] for k in range(a + W, b - W): - lo, hi = st[k - W:k], st[k:k + W] - lo, hi = lo[~np.isnan(lo)], hi[~np.isnan(hi)] - if len(lo) >= W // 2 and len(hi) >= W // 2: - if abs(np.median(hi) - np.median(lo)) > PITCH_STEP and k - cuts[-1] > int(0.12 / FRAME_S): - cuts.append(k) + if k - cuts[-1] <= int(0.12 / FRAME_S): + continue + plo, phi = st[k - W:k], st[k:k + W] + plo, phi = plo[~np.isnan(plo)], phi[~np.isnan(phi)] + moved = (len(plo) >= W // 2 and len(phi) >= W // 2 + and abs(np.median(phi) - np.median(plo)) > PITCH_STEP) + lit = abs(np.median(hi[k:k + W]) - np.median(hi[k - W:k])) > BRIGHT_STEP + if moved or lit: + cuts.append(k) cuts.append(b) for u, v in zip(cuts[:-1], cuts[1:]): - seg = st[u:v][~np.isnan(st[u:v])] - out.append((u * FRAME_S, v * FRAME_S, - float(np.median(seg)) if len(seg) else float("nan"))) + kind, pitch = classify(st, hi, u, v) + out.append((u * FRAME_S, v * FRAME_S, pitch, kind)) return out +def zoom(x, fs, t0, t1, spans): + """Every frame in a window, so a boundary can be read rather than guessed.""" + f0, st, rms, hi, peak, m = columns(x, fs) + k0, k1 = max(0, int(t0 / FRAME_S)), min(m, int(t1 / FRAME_S) + 1) + edges = {round(a, 3): f"{t} starts" for (t, a, b) in spans} + for (t_, a, b) in spans: + edges.setdefault(round(b, 3), f"{t_} ends") + + print(f"\nframes {t0:.2f}–{t1:.2f}s " + f"(level dB rel take peak · pitch st vs {TONIC:.0f} Hz · >3 kHz share)") + for k in range(k0, k1): + tt = k * FRAME_S + db = 20.0 * np.log10(max(rms[k], 1e-9) / peak) + bar = "#" * int(max(0, (db + 60.0)) / 3.0) + mark = next((f" <-- {lab}" for e, lab in edges.items() + if abs(e - tt) < FRAME_S / 2), "") + pitch = f"{st[k]:+6.1f}st" if not np.isnan(st[k]) else " ---" + print(f" {tt:6.3f} {db:6.1f} {bar:<20} {pitch} hf {hi[k]:.2f}{mark}") + + def main(): phrase = sys.argv[1] if len(sys.argv) > 1 else "w-whole-line" man = json.load(open(os.path.join(LANE, "vox4", ".manifest.json")))[phrase] - align = json.load(open(os.path.join(LANE, "samples", ".align.json"))) chart = json.load(open(os.path.join(LANE, "vox4", ".chart.json")))[phrase] slice_name = man["slice"] x, fs = sf.read(os.path.join(LANE, "samples", f"{slice_name}.wav"), dtype="float64") @@ -86,39 +168,77 @@ if x.ndim > 1: x = x.mean(axis=1) ev = events(x, fs) - words = align[slice_name]["words"] if slice_name in align else [] - print(f"{phrase} · {slice_name} · {len(ev)} sung events, " + print(f"{phrase} · {slice_name} · {len(ev)} events, " f"{len(chart['notes'])} charted units\n") print("detected events (audio only):") - for i, (a, b, s) in enumerate(ev): - print(f" {i:2d} {a:6.2f}–{b:6.2f}s {b - a:.2f}s {s:+5.1f}st") + for i, (a, b, s, kind) in enumerate(ev): + pitch = f"{s:+5.1f}st" if not np.isnan(s) else "" + print(f" {i:2d} {a:6.2f}–{b:6.2f}s {b - a:.2f}s {kind} {pitch}") # the spans the chart ACTUALLY plays — emitted by halo3 after times, # sylls, snapping, attack pre-roll and the trim. Checking the raw # alignment instead would flag boundaries we already corrected. spans = [(t, a, b) for (t, a, b) in man["spans"]] + # Which units hold which events, and how much. A boundary that splits + # one event between two ADJACENT units is legato, not damage — she + # slides from note to note and the cut has to land somewhere inside + # the slide. What is damage is audio no unit plays at all. + held = [[] for _ in ev] + for si, (t, a, b) in enumerate(spans): + for i, (ea, eb, es, kind) in enumerate(ev): + ov = max(0.0, min(b, eb) - max(a, ea)) + if ov > 0.0: + held[i].append((si, ov / (eb - ea), ov)) + + def owns(i, si): + """Does unit si hold enough of event i to be playing it?""" + return any(s_ == si and (f >= HELD_FRAC or o >= HELD_S) for s_, f, o in held[i]) + print("\nper word — which events fall in its span:") flags = 0 - for (t, a, b) in spans: - inside = [] - for i, (ea, eb, es) in enumerate(ev): - ov = max(0.0, min(b, eb) - max(a, ea)) - if ov > 0.02: - inside.append((i, ov / (eb - ea), es)) - desc = " · ".join(f"#{i} {100 * f:.0f}%@{s:+.1f}st" for i, f, s in inside) or "—" + for si, (t, a, b) in enumerate(spans): + mine = [i for i in range(len(ev)) if owns(i, si)] + notes = [i for i in mine if ev[i][3] == "NOTE" and ev[i][1] - ev[i][0] >= MIN_NOTE_S] + bad = "" - if len(inside) > 1: - bad = " <== TWO EVENTS: carrying a neighbour" - flags += 1 - elif inside and inside[0][1] < 0.75: - bad = " <== PARTIAL: clipping this event" - flags += 1 - elif not inside: + if len(notes) > 1: + bad = f" <== TWO NOTES: carrying #{notes[0]} as well as #{notes[-1]}" + elif mine: + # a trailing consonant is this word's coda UNLESS a note starts + # right after it — then it is that note's onset, and this unit + # is holding the next word's mouth. + last = ev[mine[-1]] + if last[3] in ("FRIC", "PUFF") and last[1] - last[0] >= MIN_CONS_S: + nxt = next((j for j, e in enumerate(ev) + if e[3] == "NOTE" and e[0] >= last[1] - 0.01), None) + if nxt is not None and ev[nxt][0] - last[1] < ONSET_GAP_S and nxt not in mine: + bad = " <== TRAILING CONSONANT: the next word's onset" + if not bad: + # anything of hers this unit starts but nobody finishes + for i in mine: + floor = MIN_NOTE_S if ev[i][3] == "NOTE" else MIN_CONS_S + if ev[i][1] - ev[i][0] < floor: + continue + cover = sum(f for _, f, _ in held[i]) + if cover < COVERED: + bad = f" <== CLIPPED: only {100 * cover:.0f}% of {ev[i][3].lower()} #{i} is played" + break + if not mine: bad = " <== NO EVENT in this span" + if bad: flags += 1 + + desc = " · ".join( + f"#{i} {100 * f:.0f}% {ev[i][3]}" + + (f"@{ev[i][2]:+.1f}st" if not np.isnan(ev[i][2]) else "") + for i in range(len(ev)) + for s_, f, o in held[i] if s_ == si and o > 0.02) or "—" print(f" {t:>10} {a:6.2f}–{b:6.2f}s {desc}{bad}") print(f"\n{flags} flagged of {len(spans)} words") + + if len(sys.argv) > 3: + zoom(x, fs, float(sys.argv[2]), float(sys.argv[3]), spans) if __name__ == "__main__": diff --git a/pop/loner/bin/dub.py b/pop/loner/bin/dub.py new file mode 100644 --- /dev/null +++ b/pop/loner/bin/dub.py @@ -0,0 +1,388 @@ +# dub.py — Camille's voice, singing the line in another language. +# +# @jeffrey: "we have her consent · im thinking we can use it to translate +# the song across some languages · or have like a french verse or spanish +# or danish verse · similar to how we translated the goodiepal / prutti vid +# from danish to elevenlabs". +# +# Same move as the klokkentales reel (2026-08-13): the ElevenLabs Dubbing +# API is VOICE-PRESERVING — it does not read the line in a stock voice, it +# re-sings it in hers. There the direction was da→en on Prutti; here it is +# en→fr/es/da on Camille. +# +# THE GATE, which is the lane's and not mine: consent is on record +# (@jeffrey, 2026-08-19) and synthetic voice is ALWAYS labelled. Every +# output carries `-dub-` in its name and a line in .dub.json saying +# what made it, so a file can never drift loose from the fact that a +# machine sang it. Nothing here is presented as a take she performed. +# +# WHY `dub` ALONE DOES NOT WORK HERE, measured 2026-08-19: the Dubbing API +# returned status "dubbed" with no error for fr/es/da and handed back audio +# that is still English — because its transcript came back EMPTY. dubbing_v1 +# transcribes speech, and this is 24 s of slow unaccompanied singing on held +# vowels, so it heard no words, had nothing to translate, and passed the +# source through. The klokkentales reel worked because Prutti was TALKING. +# +# So the route for a SONG is different, and it is better anyway: dubbing +# preserves the prosody of the source, and we do not want her English +# phrasing on a French verse — we want the French words on HER MELODY, +# which is the thing this lane's warp already does. Hence: +# +# clone an IVC from her SPOKEN slices (o-heres-loner, n-emo-again, +# n-i-knew-it) — real speech, which is what an IVC wants +# say the translated lyric, spoken in that voice +# then hand it to align.py + halo3's chart, and she sings the +# translation on the melody she wrote +# +# ELEVENLABS_API_KEY=... pop/.venv/bin/python pop/loner/bin/dub.py clone +# ELEVENLABS_API_KEY=... pop/.venv/bin/python pop/loner/bin/dub.py say fr +# ELEVENLABS_API_KEY=... pop/.venv/bin/python pop/loner/bin/dub.py dub fr + +import json, os, sys, time, urllib.request + +HERE = os.path.dirname(os.path.abspath(__file__)) +LANE = os.path.dirname(HERE) +REPO = os.path.dirname(os.path.dirname(LANE)) +VAULT = os.path.join(REPO, "aesthetic-computer-vault", + ".devcontainer", "envs", "devcontainer.env") +API = "https://api.elevenlabs.io/v1" +SOURCE = os.path.join(LANE, "samples", "f-whole-line.wav") # the whole sentence +LANGS = {"fr": "French", "es": "Spanish", "da": "Danish", "de": "German", + "it": "Italian", "pt": "Portuguese", "ja": "Japanese", + "ru": "Russian", "hi": "Hindi"} + +# The whole song is one sentence, so each translation is one sentence too. +# Kept literal rather than singable — the melody does the singing, and a +# rhyme scheme she never wrote would be us writing her lyric for her. +LYRIC = { + "en": "sitting curled up in myself, i think of a stone, " + "just waiting very patiently for time to pass", + "fr": "assise recroquevillée en moi-même, je pense à une pierre, " + "qui attend très patiemment que le temps passe", + "es": "sentada acurrucada en mí misma, pienso en una piedra, " + "que espera muy pacientemente a que pase el tiempo", + "da": "jeg sidder krøllet sammen i mig selv, jeg tænker på en sten, " + "der bare venter meget tålmodigt på at tiden går", + "ru": "сижу, свернувшись в себе, я думаю о камне, " + "который очень терпеливо ждёт, пока пройдёт время", + "hi": "अपने भीतर सिमटी हुई बैठी हूँ, मैं एक पत्थर के बारे में सोचती हूँ, " + "जो बहुत धीरज से समय के बीतने का इंतज़ार कर रहा है", +} + +# her SPOKEN slices — an IVC trained on singing learns the singing, and +# then every line it speaks arrives on that melody +SPOKEN = ["o-heres-loner", "n-emo-again", "n-i-knew-it"] + +# …but eight seconds is not a voice, it is an impression of one. @jeffrey: +# "these aren't using her voice · like we did with prutti". The Prutti clone +# had a whole reel behind it. `clone --all` uses the WHOLE archive instead: +# nineteen posts, 7.7 minutes, downsampled to fit the upload budget. +# +# ONE take is excluded and must stay excluded: 6988619239657622790 is the +# ensemble performance, with @jeffrey and Alex singing on it. Their voices +# are not Camille's and were not consented into this clone; a model trained +# on all three is not her. +ENSEMBLE = "6988619239657622790" +VOICE_NAME = "Camille Klein · loner IVC (consented)" + + +def key(): + k = os.environ.get("ELEVENLABS_API_KEY") + if k: + return k + with open(VAULT) as f: + for line in f: + if line.startswith("ELEVENLABS_API_KEY="): + return line.split("=", 1)[1].strip().strip("'\"") + raise SystemExit("no ELEVENLABS_API_KEY (env or vault devcontainer.env)") + + +def post_multipart(url, k, fields, filepath): + b = "----acdub" + body = b"" + for name, val in fields.items(): + body += (f"--{b}\r\nContent-Disposition: form-data; name=\"{name}\"\r\n\r\n" + f"{val}\r\n").encode() + with open(filepath, "rb") as f: + data = f.read() + body += (f"--{b}\r\nContent-Disposition: form-data; name=\"file\"; " + f"filename=\"{os.path.basename(filepath)}\"\r\n" + f"Content-Type: audio/wav\r\n\r\n").encode() + data + b"\r\n" + body += f"--{b}--\r\n".encode() + req = urllib.request.Request(url, data=body, headers={ + "xi-api-key": k, "Content-Type": f"multipart/form-data; boundary={b}"}) + with urllib.request.urlopen(req, timeout=300) as r: + return json.load(r) + + +def get(url, k, raw=False, timeout=300): + req = urllib.request.Request(url, headers={"xi-api-key": k}) + with urllib.request.urlopen(req, timeout=timeout) as r: + return r.read() if raw else json.load(r) + + +def post_files(url, k, fields, paths): + b = "----acdub" + body = b"" + for name, val in fields.items(): + body += (f"--{b}\r\nContent-Disposition: form-data; name=\"{name}\"\r\n\r\n" + f"{val}\r\n").encode() + for fp in paths: + with open(fp, "rb") as f: + data = f.read() + body += (f"--{b}\r\nContent-Disposition: form-data; name=\"files\"; " + f"filename=\"{os.path.basename(fp)}\"\r\n" + f"Content-Type: audio/wav\r\n\r\n").encode() + data + b"\r\n" + body += f"--{b}--\r\n".encode() + req = urllib.request.Request(url, data=body, headers={ + "xi-api-key": k, "Content-Type": f"multipart/form-data; boundary={b}"}) + with urllib.request.urlopen(req, timeout=300) as r: + return json.load(r) + + +def voice_path(): + return os.path.join(LANE, "vox-dub", ".voice.json") + + +def clone(k, whole_archive=False): + if whole_archive: + import glob, subprocess, tempfile + src = sorted(glob.glob(os.path.join(LANE, "source", "*-48k.wav"))) + src = [p for p in src if ENSEMBLE not in os.path.basename(p)] + tmp = tempfile.mkdtemp(prefix="acdub-") + paths, total = [], 0.0 + for f in src: # 22 kHz mono mp3 — the upload has a budget + d = os.path.join(tmp, os.path.basename(f).replace("-48k.wav", ".mp3")) + subprocess.run(["ffmpeg", "-y", "-v", "error", "-i", f, "-ac", "1", + "-ar", "22050", "-b:a", "96k", d], check=True) + paths.append(d) + total += os.path.getsize(d) + print(f" {len(paths)} takes, {total / 1e6:.1f} MB — excluded the " + f"ensemble take {ENSEMBLE} (@jeffrey and Alex are on it)") + else: + paths = [os.path.join(LANE, "samples", f"{n}.wav") for n in SPOKEN] + paths = [p for p in paths if os.path.exists(p)] + if not paths: + raise SystemExit("no audio to clone from") + print(f"→ cloning from {len(paths)} spoken slices: " + f"{', '.join(os.path.basename(p) for p in paths)}") + r = post_files(f"{API}/voices/add", k, { + "name": VOICE_NAME, + "description": "Consented IVC of Camille Klein (@cksuperstore) for the " + "loner remix. SYNTHETIC VOICE — label on any release.", + }, paths) + vid = r.get("voice_id") + os.makedirs(os.path.join(LANE, "vox-dub"), exist_ok=True) + json.dump(dict(voice_id=vid, name=VOICE_NAME, + sources=[os.path.basename(p) for p in paths], + synthetic=True, + consent="Camille Klein (@cksuperstore), via @jeffrey 2026-08-19"), + open(voice_path(), "w"), indent=1) + print(f" ✓ voice_id {vid} → {voice_path()}") + return vid + + +def say(k, lang): + vp = voice_path() + if not os.path.exists(vp): + raise SystemExit("no voice yet — run: dub.py clone") + vid = json.load(open(vp))["voice_id"] + text = LYRIC[lang] + body = json.dumps({ + "text": text, "model_id": "eleven_multilingual_v2", + "voice_settings": {"stability": 0.55, "similarity_boost": 0.85, + "style": 0.20, "use_speaker_boost": True}, + }).encode() + req = urllib.request.Request( + f"{API}/text-to-speech/{vid}", data=body, + headers={"xi-api-key": k, "Content-Type": "application/json", + "Accept": "audio/mpeg"}) + with urllib.request.urlopen(req, timeout=300) as r: + audio = r.read() + out_dir = os.path.join(LANE, "vox-dub") + os.makedirs(out_dir, exist_ok=True) + dest = os.path.join(out_dir, f"spoken-{lang}.mp3") + open(dest, "wb").write(audio) + print(f" ✓ {LANGS[lang]}: {dest} ({len(audio) // 1024} KB)") + print(f" “{text}”") + return dest + + +# A native speaker of each language, to PERFORM the line before her voice +# is mapped onto it. Which premade voice matters less than that it is +# female and unhurried — speech-to-speech transfers timbre, not timing, so +# whatever phrasing this voice chooses is the phrasing she will have. +CARRIER = "XrExE9yKIg1WjnnlVkGX" # Matilda — even, unhurried + + +def sts(k, lang): + """TTS the translation with a carrier voice, then wear her timbre. + + Better than TTS straight from the IVC because the model only has to + move TIMBRE — the prosody is already a real reading of a real French + sentence, rather than an English-trained clone guessing at one. It is + also what the Prutti dub was doing underneath. + """ + vp = voice_path() + if not os.path.exists(vp): + raise SystemExit("no voice yet — run: dub.py clone --all") + vid = json.load(open(vp))["voice_id"] + + body = json.dumps({ + "text": LYRIC[lang], "model_id": "eleven_multilingual_v2", + "voice_settings": {"stability": 0.60, "similarity_boost": 0.75, + "style": 0.0, "use_speaker_boost": True}, + }).encode() + req = urllib.request.Request( + f"{API}/text-to-speech/{CARRIER}", data=body, + headers={"xi-api-key": k, "Content-Type": "application/json", + "Accept": "audio/mpeg"}) + with urllib.request.urlopen(req, timeout=300) as r: + carrier = r.read() + + out_dir = os.path.join(LANE, "vox-dub") + os.makedirs(out_dir, exist_ok=True) + carrier_path = os.path.join(out_dir, f".carrier-{lang}.mp3") + open(carrier_path, "wb").write(carrier) + + b = "----acsts" + fields = {"model_id": "eleven_multilingual_sts_v2", + "voice_settings": json.dumps({"stability": 0.45, + "similarity_boost": 0.90, + "style": 0.0, + "use_speaker_boost": True})} + payload = b"" + for name, val in fields.items(): + payload += (f"--{b}\r\nContent-Disposition: form-data; name=\"{name}\"\r\n\r\n" + f"{val}\r\n").encode() + payload += (f"--{b}\r\nContent-Disposition: form-data; name=\"audio\"; " + f"filename=\"carrier.mp3\"\r\nContent-Type: audio/mpeg\r\n\r\n" + ).encode() + carrier + b"\r\n" + payload += f"--{b}--\r\n".encode() + req = urllib.request.Request( + f"{API}/speech-to-speech/{vid}", data=payload, + headers={"xi-api-key": k, "Accept": "audio/mpeg", + "Content-Type": f"multipart/form-data; boundary={b}"}) + with urllib.request.urlopen(req, timeout=600) as r: + audio = r.read() + dest = os.path.join(out_dir, f"sts-{lang}.mp3") + open(dest, "wb").write(audio) + print(f" ✓ {LANGS[lang]}: {dest} ({len(audio) // 1024} KB)") + return dest + + +def scribe(k, lang): + """Word timestamps for a translation — the shape of ITS words. + + @jeffrey: "per language we should be able to map the shape of the + words etc". singdub was finding syllables in the audio with an energy + detector, which is guessing; here the text is already known, so the + words come back labelled and a French verse can be charted word by + word the way the English one was. Same ElevenLabs scribe step the + klokkentales reel used for its karaoke subs. + """ + # `lang` may also name a SLICE — scribing her own takes is the same + # job as scribing a translation, and singdub needs word spans for any + # take it is asked to put on the chart. + slice_wav = os.path.join(LANE, "samples", f"{lang}.wav") + src = os.path.join(LANE, "vox-dub", f"sts-{lang}.mp3") + if os.path.exists(slice_wav): + src = slice_wav + elif not os.path.exists(src): + raise SystemExit(f"no sts-{lang}.mp3 and no samples/{lang}.wav") + b = "----acscribe" + code = lang if lang in LANGS else "en" + fields = {"model_id": "scribe_v1", "language_code": code, + "timestamps_granularity": "word", "diarize": "false"} + payload = b"" + for name, val in fields.items(): + payload += (f"--{b}\r\nContent-Disposition: form-data; name=\"{name}\"\r\n\r\n" + f"{val}\r\n").encode() + with open(src, "rb") as f: + data = f.read() + mime = "audio/wav" if src.endswith(".wav") else "audio/mpeg" + payload += (f"--{b}\r\nContent-Disposition: form-data; name=\"file\"; " + f"filename=\"{os.path.basename(src)}\"\r\n" + f"Content-Type: {mime}\r\n\r\n").encode() + data + b"\r\n" + payload += f"--{b}--\r\n".encode() + req = urllib.request.Request( + f"{API}/speech-to-text", data=payload, + headers={"xi-api-key": k, + "Content-Type": f"multipart/form-data; boundary={b}"}) + with urllib.request.urlopen(req, timeout=600) as r: + res = json.load(r) + + words = [w for w in res.get("words", []) if w.get("type") == "word"] + out = os.path.join(LANE, "vox-dub", ".words.json") + allw = json.load(open(out)) if os.path.exists(out) else {} + allw[lang] = [dict(t=w["text"], start=round(w["start"], 3), + end=round(w["end"], 3)) for w in words] + json.dump(allw, open(out, "w"), indent=1, ensure_ascii=False) + print(f" ✓ {LANGS.get(lang, lang)}: {len(words)} words → {out}") + print(" " + " ".join(w["text"] for w in words)) + return allw[lang] + + +def main(): + argv = sys.argv[1:] + k = key() + if argv and argv[0] == "clone": + clone(k, whole_archive="--all" in argv); return + if argv and argv[0] == "scribe": + for lang in argv[1:] or ["fr"]: + scribe(k, lang) + return + if argv and argv[0] == "sts": + for lang in [a for a in argv[1:] if a in LANGS] or ["fr"]: + sts(k, lang) + return + if argv and argv[0] == "say": + for lang in [a for a in argv[1:] if a in LANGS] or ["fr"]: + say(k, lang) + return + langs = [a for a in argv if a in LANGS] or ["fr"] + k = key() + out_dir = os.path.join(LANE, "vox-dub") + os.makedirs(out_dir, exist_ok=True) + receipt_path = os.path.join(out_dir, ".dub.json") + receipt = json.load(open(receipt_path)) if os.path.exists(receipt_path) else {} + + for lang in langs: + print(f"→ {LANGS[lang]} ({lang}) — dubbing {os.path.basename(SOURCE)}") + job = post_multipart(f"{API}/dubbing", k, { + "target_lang": lang, "source_lang": "en", "num_speakers": "1", + "name": f"loner-{lang}", + }, SOURCE) + did = job.get("dubbing_id") + if not did: + print(f" ! no dubbing_id: {job}"); continue + + for _ in range(120): # ~10 min ceiling + st = get(f"{API}/dubbing/{did}", k) + s = st.get("status") + if s == "dubbed": + break + if s == "failed": + print(f" ! failed: {st.get('error')}"); did = None; break + time.sleep(5) + if not did: + continue + + audio = get(f"{API}/dubbing/{did}/audio/{lang}", k, raw=True) + dest = os.path.join(out_dir, f"whole-line-dub-{lang}.mp3") + open(dest, "wb").write(audio) + # …and the label travels with the file, not just in a README + receipt[lang] = dict( + language=LANGS[lang], source=os.path.relpath(SOURCE, LANE), + dubbing_id=did, engine="elevenlabs/dubbing", + synthetic=True, consent="Camille Klein (@cksuperstore), via @jeffrey", + note="SYNTHETIC VOICE — her voice model singing a translation; " + "not a take she performed. Label on any release.") + json.dump(receipt, open(receipt_path, "w"), indent=1, sort_keys=True) + print(f" ✓ {dest} ({len(audio) // 1024} KB)") + + print(f"\nreceipt: {receipt_path}") + + +if __name__ == "__main__": + main() diff --git a/pop/loner/bin/halo3.py b/pop/loner/bin/halo3.py --- a/pop/loner/bin/halo3.py +++ b/pop/loner/bin/halo3.py @@ -40,13 +40,15 @@ # chart from, so the band's notes ARE her notes. # # pop/.venv/bin/python pop/loner/bin/halo3.py -import json, os +import json, os, sys import numpy as np import soundfile as sf import pyworld as pw HERE = os.path.dirname(os.path.abspath(__file__)) LANE = os.path.dirname(HERE) +sys.path.insert(0, os.path.join(os.path.dirname(LANE), "lib")) +from nervox import waver as nervox_waver, flange as nervox_flange VOX4 = os.path.join(LANE, "vox4") CDIR = os.path.join(LANE, "c") os.makedirs(VOX4, exist_ok=True) @@ -59,9 +61,28 @@ FRAME_S = FRAME_MS / 1000.0 FLOOR = 140.0 SNAP = 0.92 # THE REGULATION (v3 was 0.70) SMOOTH_MS = 45.0 +GLIDE_ST_S = 18.0 # above this rate of change she is SLIDING, not + # holding a note — and a slide is not out of tune FORMANT_DB = 1.6 AIR_DB = 2.5 BREATH = 0.14 +# THE SIBILANT RESTORE — @jeffrey: "the opening 's' is not hearable". +# It was never missing. In her source the /s/ of "sitting" runs 15 dB under +# the vowel that follows it; in the render that gap opens to 19, because +# the voiced half gets the formant lift, the air shelf and the breath and +# the unvoiced half — which is copied straight from the warped source — +# gets none of them. Four dB does not sound like much until the floor is +# under it, and then the consonant is simply gone. +# +# So: find the frames that are UNVOICED AND BRIGHT (a fricative is dim but +# bright — the same test audit.py uses to call an event FRIC) and give them +# back the level the voiced frames were given, plus a little more, because +# a sung sibilant in a mix needs to beat a hi-hat and not just itself. +# Ramped over 30 ms so it lifts the consonant rather than gating it. +SIB_DB = 8.0 # the lift on an unvoiced bright frame +SIB_HI_HZ = 3000.0 # "bright" is measured above here… +SIB_SHARE = 0.45 # …and means this much of the frame's energy +SIB_RAMP_S = 0.030 HALO_DARK_HZ = 5500.0 HALO_BREATH_X = 1.5 UNVOICED_W = 0.18 # consonant share of any stretch @@ -110,33 +131,82 @@ """WORLD analysis is 2.3 s a slice and depends only on the audio and the analysis constants — never on the chart. Tuning a bar re-ran it every time. Cached on disk, keyed by the file's mtime and the parameters, so an edit pays for synthesis only.""" - key = f"{os.path.basename(path)}-{int(os.path.getmtime(path))}-{FRAME_MS}-{FLOOR}-{SNAP}-{SMOOTH_MS}" + key = (f"{os.path.basename(path)}-{int(os.path.getmtime(path))}" + f"-{FRAME_MS}-{FLOOR}-{SNAP}-{SMOOTH_MS}-{GLIDE_ST_S}-nervox1-fitfloor1") dest = os.path.join(CACHE, key + ".npz") if os.path.exists(dest): z = np.load(dest) return dict(x=x, fs=fs, f0=z["f0"], f0c=z["f0c"], sp=z["sp"].astype(np.float64), ap=z["ap"].astype(np.float64), - voiced=z["voiced"]) + voiced=z["voiced"], rate=z["rate"]) a = analyze(x, fs) os.makedirs(CACHE, exist_ok=True) - np.savez(dest, f0=a["f0"], f0c=a["f0c"], voiced=a["voiced"], + np.savez(dest, f0=a["f0"], f0c=a["f0c"], voiced=a["voiced"], rate=a["rate"], sp=a["sp"].astype(np.float32), ap=a["ap"].astype(np.float32)) return a def analyze(x, fs): - f0_raw, t = pw.harvest(x, fs, f0_floor=FLOOR, f0_ceil=600.0, frame_period=FRAME_MS) + # THE FLOOR HAS TO FIT THE VOICE. FLOOR was set for Camille's take, + # which sits at 283 Hz; harvest below its floor does not return a low + # note, it returns a wrong one — usually the second harmonic — or + # nothing. Half the bank sings lower than she does. rq, sh and pf are + # all around 121 Hz, well UNDER the 140 Hz floor, so every one of them + # was analysed from a broken pitch track and everything downstream — + # the snap, the melody lock, THE HOLD — was reading it. @jeffrey: "it + # sounds so glitchy". That is what it was. + # + # So the range is measured before it is used: one wide probe to find + # where this voice actually lives, then the real analysis bracketed + # around it. Wide-open on every take would be worse than a fixed + # floor — the lower you let harvest look, the more freely it picks a + # subharmonic on a bright voice — so the bracket is snug. + # …and it only ever WIDENS. The spine is the record, and a bracket + # recomputed from a probe would have moved her ceiling from 600 to 849 + # on the next rebuild for no reason at all. Nothing moves unless the + # voice does not fit: FLOOR/600 stands for anyone it already suits. + probe, _t = pw.harvest(x, fs, f0_floor=55.0, f0_ceil=900.0, + frame_period=FRAME_MS) + voiced_probe = probe[probe > 0] + med = float(np.median(voiced_probe)) if len(voiced_probe) else TONIC + floor, ceil = FLOOR, 600.0 + if med * 0.55 < floor: # a voice lower than hers + floor = max(55.0, med * 0.55) + if med * 2.0 > ceil: # …or higher + ceil = min(1000.0, med * 3.0) + f0_raw, t = pw.harvest(x, fs, f0_floor=floor, f0_ceil=ceil, frame_period=FRAME_MS) f0 = pw.stonemask(x, f0_raw, t, fs) - fft = pw.get_cheaptrick_fft_size(fs, f0_floor=FLOOR) - sp = pw.cheaptrick(x, f0, t, fs, fft_size=fft, f0_floor=FLOOR) + fft = pw.get_cheaptrick_fft_size(fs, f0_floor=floor) + sp = pw.cheaptrick(x, f0, t, fs, fft_size=fft, f0_floor=floor) ap = pw.d4c(x, f0, t, fs, fft_size=fft) voiced = f0 > 0 corr = np.zeros_like(f0) if voiced.any(): corr[voiced] = -cents_to_grid(f0[voiced]) * SNAP + # A SLIDE IS NOT OUT OF TUNE. Smoothing the correction keeps a glide + # SMOOTH but still drags it onto the grid tone by tone, so a fast + # scoop comes out as a staircase — @jeffrey on the leap into "pa": + # "it feels a little extreme · maybe we need better auto tune on + # it". That leap is 8.4 semitones in 30 ms. So the snap now fades + # out wherever her pitch is genuinely MOVING. f0 is smoothed over + # 60 ms before the derivative, so vibrato (±0.5 st at ~5 Hz, ~16 + # st/s instantaneous) averages away and only a real transition + # survives; unvoiced gaps are interpolated across first, or their + # edges would read as infinite glides and disable the snap at every + # onset. + st = 12.0 * np.log2(np.maximum(f0, 1e-6) / TONIC) + idx = np.arange(len(f0)) + st = np.interp(idx, idx[voiced], st[voiced]) + rate = np.abs(np.gradient(smooth(st, int(60.0 / FRAME_MS)), + FRAME_MS / 1000.0)) + corr *= np.clip(1.0 - (rate - GLIDE_ST_S) / GLIDE_ST_S, 0.0, 1.0) + else: + rate = np.zeros_like(f0) corr = smooth(corr, int(SMOOTH_MS / FRAME_MS)) f0c = np.where(voiced, f0 * 2.0 ** (corr / 1200.0), 0.0) - return dict(x=x, fs=fs, f0=f0, f0c=f0c, sp=sp, ap=ap, voiced=voiced) + # `rate` travels with the analysis so nervox wavers exactly the frames + # the snap regulated, and lets go exactly where the snap let go. + return dict(x=x, fs=fs, f0=f0, f0c=f0c, sp=sp, ap=ap, voiced=voiced, rate=rate) def vuv_mask(voiced, fs, n): @@ -187,7 +257,6 @@ # "myself" under the OpenAI alignment, where # "curled" is ONE word — under whisper.cpp's # sub-word tokens it was cur+led and this was 5. # durs are POST-split indices. - "splits": [0], # The bar map, one phrase per bar (@jeffrey: # "curled up should be bar 1 — not bar 1 and # half of bar 2 · and in my should be bar @@ -268,7 +337,18 @@ # to halfway past beat 3 — in takes the # half beat (2.0, 1.23×) and my gives it # back (1.5, 1.07×), so self keeps bar 3 # and nothing downstream moves. - 4: 1.5, 5: 1.5, 6: 2.0, + # IN takes two full beats — @jeffrey: + # "'in' should last two full beats and my + # should start on bar 2:3 now". At 1.5 it + # ran 1.10× and handed "my" the 2:2.5 line; + # at 2 it is 1.47×, still her voice and + # nowhere near the 1.8 hold, and "my" opens + # square on bar 2 beat 3. + # SELF grows so "i" opens on bar 3:3 — + # @jeffrey: "'i' should move so it starts + # on bar 3:3 now". self goes 2 → 2.5 + # (1.02× → 1.23×), which lands i on 14.0. + 4: 2.0, 5: 1.5, 6: 2.5, # think 1 (1.17×, her own speed — at 2 # it was a 2.3× held tone), so OF keeps # its 4 beats at 1.01×, her real octave, @@ -278,8 +358,99 @@ # my on bar 2 beat 4; "i" takes the # freed beat (1.78×, still her voice) # so "of" keeps beat 19 and stone its # bar 6 beat 2. + # …and "i" pays for it. Giving IN its + # second beat pushed the whole back half + # off its lines — self 2:4.5, think 3:4.5, + # stone 6:1.5. "i" was the one word with + # slack anywhere near it: 0.71 s stretched + # over 2 beats at 1.39×. At 1.5 it runs + # 1.04×, her own speed, and think · of · a · + # stone are all back on the lines they were + # tuned to. Only self and i sit a half beat + # later than before. + # THINK on bar 4:1 — @jeffrey: "and think + # should start on bar 4:1". "i" takes its + # second beat back (1.04× → 1.39×, still + # well under the 1.8 hold) so it ends on + # 16.0 and think opens the bar. + # 2.0, and it must STAY a beat value. + # The +0.22 slice shift caught this one + # by accident — it is the only `durs` + # entry that sits alone on a line before + # a comment, which is exactly the shape + # the times-bumping pass looked for — so + # "i" became 2.22 and every word after it + # sat 0.22 of a beat late: @jeffrey, + # "these boundaries are still off · check + # the rest of the words too". durs are + # BEATS; times are SECONDS. Nothing in + # here shifts with the slice. 7: 2.0, - 8: 2.0, 9: 4.0, 10: 3.0, 11: 3.0, + # …and "a" pays this one, for free. Once + # stone took back its own /s/, "a" was + # 0.43 s of audio over 3 beats — 3.4×, far + # past the 1.8 hold line, so it is already + # a synthesized grid tone rather than her + # voice. 2.5 beats is 2.9×: the same + # synthetic hold, half a beat shorter, and + # stone is back on bar 6:1 with everything + # after it. + # "a" pays again — and this is the last + # half beat it has. @jeffrey set its floor + # at two ("a should be at least two beats, + # its too short now"), so anything after + # this has to come from "of" or run + # downstream. + # STONE'S PEAK ON THE BAR 6 EDGE — + # @jeffrey: "'stone' should shift just a + # little · so its peak lands on the bar 6 + # edge". The block was already on 6:1, but + # the block now opens with the /s/ it took + # back, and a consonant rides 1:1 through + # the warp — so her NOTE arrived 0.75 of a + # beat late and her peak 1.24 beats late. + # PEAK_LEAD_MAX_S is 90 ms, a lean, so this + # is the grid's job. Aligning the RMS PEAK + # was wrong — @jeffrey: "whoa now stone + # starts too soon". The peak sits 0.21 s + # after her vowel, so peak-on-the-beat + # opened the block 1.24 beats early and the + # /s/ arrived most of a bar before 6. Her + # VOWEL is the anchor a listener hears: it + # starts 0.37 s in, consonants ride ~1:1, + # so the slot opens 0.75 of a beat early at + # 23.25 and the note lands on 24.0 with the + # sibilant leading into it. stone holds + # 3.75 (1.39×) and still hands "just" the + # bar 6:4 line; of keeps its 4, and "a" + # takes 1.25 — 1.43×, her own voice rather + # than the 2.3× synthetic hold it was at 2 + # beats. + # …and then right a bit more — @jeffrey: + # "it should move to the right a bit + # more". Half a beat, bought from "of" + # (4 → 4.5, 1.37×; it is the held octave + # and takes the extra) rather than from + # "a", which at 1.75 would tip back over + # the 1.8 hold and go synthetic again. + # stone opens 23.75, its /t/ lands 24.51. + # JUST ON BAR 7 — @jeffrey: "and 'just' + # should start on bar 7 now". stone holds + # the extra beat itself (3.25 → 4.25, + # 1.57×, still under the 1.8 hold) rather + # than moving, so its /t/ stays on 24.51 + # and only what follows "just" shifts. + # OF ENDS ON BAR 5:3 — @jeffrey: "'of' + # should end at bar 5:3 start, and 'a' + # should start there". of back to 4 + # (18–22, 1.22×). That pins BOTH of a's + # edges — 22 to stone's 23.75 — so it is + # 1.75 beats, 2.0×, just over the hold: "a" + # is a sustained grid tone again rather + # than her voice. That is the cost of the + # two placements, and it is the connective + # in "of a stone", so it holds well. + 8: 2.0, 9: 4.0, 10: 1.75, 11: 4.25, # very longer, patiently slower # the tail on bars: just and waiting # a bar each (waiting on bar 8:1), @@ -289,31 +460,100 @@ # too fast and abrupt # waiting splits like sitting did, so # "ing" lands on the half bar 12: 4.0, 13: 2.0, 14: 2.0, 15: 2.0, - 16: 2.0, 17: 2.0, 18: 2.5, 19: 2.5 }, + # BAR 10 HOLDS pa AND tient, BAR 11 OPENS + # WITH ly — @jeffrey: "can pa and tient be + # just within bar 10?" · "and ly should be + # bar 11 first three beats". tient 2.5 → 2 + # ends it on 44.0 (0.94×, a hair quicker + # than she sang it) so pa·tient fill bar 10 + # exactly, and ly takes the freed half beat + # itself — 3 beats, 44–47, at 1.76×, just + # under the 1.8 hold, which is right for + # the held last syllable of the word. "for" + # keeps bar 11:4 and nothing downstream + # moves. + 16: 2.0, 17: 2.0, 18: 2.0, 19: 2.0, + # for and time were still the auto scale's + # — @jeffrey: "and for is two beats too" · + # "and time is 4 beats". Pinning them ends + # the auto scale on this line entirely: + # every unit's length is now a decision. + # time at 4 is 1.80×, right on the hold + # line, so it sustains as a grid tone — + # which is what a held "time" wants. + # …then @jeffrey squared the tail off: + # "'ly' should be two beats" · "'for' + # should be two beats" · "and time to pass + # each of those is 1 full bar". ly 3 → 2 + # pulls for back to 11:3, and from there + # the last three words own a bar each — + # time bar 12, to bar 13, pass bar 14. + # "to" at 4 beats is 2.05×, over the hold, + # so it sustains as a grid tone; "pass" + # lands at 1.65× and stays her voice. + 20: 2.0, 21: 4.0, 22: 4.0, 23: 4.0 }, # words whose syllables carry a melody must not # be flattened to one tone by THE HOLD # patiently is pa·tient·ly, three notes - "sylls": { 4: [(None, "my"), (4.50, "self")], - 11: [(None, "wait"), (13.70, "ing")], - 12: [(None, "ve"), (15.05, "ry")], - 13: [(None, "pa"), (16.80, "tient"), - (17.70, "ly")] }, + # ve|ry and pa|tient were both cut off the + # brightness column (audit's zoom), not by ear. + # very is legato — no level dip anywhere, because + # /r/ is an approximant — so the only edge is the + # note: she holds A#3 flat to 15.165 and only then + # glides to G#3. The old 15.05 opened "ry" 115 ms + # inside "ve"'s pitch, so ry sang ve's note first. + # patiently's /ʃ/ runs 16.655–16.825 (hf 0.9+, level + # −30); the old 16.80 left 145 ms of it in "pa" and + # gave "tient" the last 25 ms of its own consonant. + # sit|ting is MEASURED now, not found. The + # automatic fricative split put it at 0.865, + # 140 ms inside her "sit" vowel while it was + # still at −7 dB — it had been fine until unit 0 + # reached back for the /s/, which moved every + # landmark the search leans on. Her vowel holds + # to 0.945, decays into the /t/ closure and + # bottoms at 1.015; the burst is 1.025 and "ting" + # arrives 1.035 on its own note. The closure + # belongs to the syllable it opens. + "sylls": { 0: [(None, "sitting·a"), (1.00, "sitting·b")], + 4: [(None, "my"), (4.72, "self")], + 11: [(None, "wait"), (13.92, "ing")], + 12: [(None, "ve"), (15.39, "ry")], + 13: [(None, "pa"), (16.875, "tient"), + (17.92, "ly")] }, # "pa" stays on the F4 she sings — the leap up # from very's A#3 is the point of the phrase, # not something to smooth away. (`shift` is # still there if a unit ever needs moving.) # source seconds, read off her onsets, for the # words whisper-1 mistimed. PRE-split indices. - "end": 24.25, - "times": { 1: 1.51, # curled — the aligner cut at 1.465, + # 24.33 — her /s/ tapers out at 24.30. In the + # slice's clock (see the cap below). + "end": 24.55, + # THE S OF SITTING — @jeffrey: "id love a stronger + # 'ssss' sound at start of first english + # 'sittting too'". Her sibilant runs 0.065–0.295 + # in the SOURCE and the slice used to open at + # 0.280, so 215 ms of a 230 ms /s/ was thrown + # away before anything here ever saw it. The + # slice now starts at 0.06 — and every + # slice-relative time in this chart moved +0.22 + # with it — so the whole sibilant exists; this + # pin is what makes unit 0 actually HOLD it, + # rather than opening at the aligner's word start + # 220 ms later. With lead 0 it plays 1:1 as the + # pre-roll, so the record opens on her ssss and + # lands on the downbeat. + "times": { 0: 0.0, + 1: 1.73, # curled — the aligner cut at 1.465, # inside ting's decay (18% there, # 8% at 1.48), so curled opened # holding the end of "sitting". # Her /k/ closure is 1.52–1.58 and # belongs to curled; ting's decay # bottoms out at 1.50. - 2: 2.40, - 7: 7.15, # of — her onset is 7.17; + 2: 2.62, + 7: 7.37, # of — her onset is 7.17; # the aligner opened its span # 115 ms of silence early # up — the alignment put this @@ -323,12 +563,47 @@ # curled's block ended on the # first 20 ms of "up". Her level # valley is 2.38–2.42; the # boundary belongs in it. - 11: 12.70, # waiting - 12: 14.40, # very - 14: 18.54, # for - 15: 19.48, # time - 16: 21.20, # to - 17: 23.00 }, # pass + # A CONSONANT BELONGS TO THE NOTE IT + # LEADS INTO. The aligner hands a word + # over where the transcript does, which + # is at the vowel — so four words were + # opening after their own mouth had + # already played inside the word before. + # Each of these is the brightness column + # (audit's zoom), not a guess. + 9: 9.41, # stone — her /s/ is 290 ms + # of hf 0.99 running + # 9.19–9.48, then the /t/ + # closure to 9.56 and the + # vowel at 9.60. Opening at + # 9.555 put the WHOLE + # sibilant in "a" and let + # stone enter as "-tone". + 10: 11.315, # just — the /dʒ/ affricate + # steps up at 11.095 and + # brightens to 0.9 by 11.115; + # opening at 11.195 caught + # its last 20 ms and dropped + # the rest on the floor. + 11: 12.92, # waiting + 12: 14.62, # very + 13: 16.12, # patiently — her /p/ and the + # breath into it run + # 15.90–15.98 and her voice + # arrives at 15.98; "ry" was + # holding all of it. + 14: 18.76, # for + 15: 19.535, # time — the /t/ burst is + # 30 ms of hf 0.97 at 19.315 + # with its aspiration to + # 19.42. At 19.48 the word + # started on its vowel and + # "for" said the t. + 16: 21.42, # to + 17: 23.03 }, # pass — /p/ + breath from + # 22.81, voice from 22.945. + # 23.00 was 55 ms into her + # own attack. # rest AFTER the given unit, in beats # "the in should start sooner — at start of # bar 2": the rest after up goes entirely, so @@ -640,7 +915,24 @@ lead_cap = int(round(PEAK_LEAD_MAX_S / FRAME_S)) ants, voiced_at = [], [] # frames ahead of the beat for (s0, s1) in unit_src: v0 = s0 - lim = min(s0 + int(0.20 / FRAME_S), s1 - 1, F - 1) + # TWO MECHANISMS, TWO WINDOWS. 0.20 s cannot see a real sibilant — + # "sitting" opens on 235 ms of /s/ — so for the FIRST unit the + # search gave up mid-fricative, decided the word had no unvoiced + # runway, and set Z = 0. The render then carried 330 ms of pre-roll + # that lead_in never reported and the engine placed the whole vocal + # that late: @jeffrey, "seems like all other utterances got bumped". + # + # But widening it for EVERY unit is a different change, and a worse + # one. `ants` also decides how far a word leans back into the word + # before it, and the back half of this line is almost all + # consonant-initial — just /dʒ/, for /f/, time /t/, to /t/, pass + # /p/. At 0.40 they all started leaning at once and the whole + # second half moved: "just waiting very patiently for time to pass + # is all offset". The pickup is about the take's opening; the lean + # is a per-word gesture with its own calibration. Wide window for + # unit 0 only. + wide = 0.40 if len(voiced_at) == 0 else 0.20 + lim = min(s0 + int(wide / FRAME_S), s1 - 1, F - 1) while v0 < lim and not a["voiced"][v0]: v0 += 1 if not a["voiced"][min(v0, F - 1)]: @@ -798,6 +1090,17 @@ xw = np.zeros(n) take = min(n, pos.size) xw[:take] = x[pos[:take]] out = mask * y + (1 - mask) * xw + # …and now give the fricatives back what the voiced half was given. + # sp_o is already the post-lift envelope, so the brightness test + # reads the frame as it will be heard. + band = freqs > SIB_HI_HZ + share = sp_o[:, band].sum(1) / (sp_o.sum(1) + 1e-12) + fric = (~voiced_o) & (share > SIB_SHARE) + if fric.any(): + gf = np.where(fric, 10.0 ** (SIB_DB / 20.0), 1.0) + gf = smooth(gf, max(1, int(SIB_RAMP_S / FRAME_S))) + g = np.repeat(gf, int(fs * FRAME_S)) + out *= g[:n] if len(g) >= n else np.pad(g, (0, n - len(g)), constant_values=1.0) for (q0, q1) in rests: # a long rest is her room tone ping-ponged; without this it # pulses. Let the breath sound, then settle to almost nothing. @@ -867,6 +1170,64 @@ manifest = _seed(os.path.join(VOX4, ".manifest.json")) chart_c = [] # (phrase, lead_in_s, beats_total, [(beat, dur, st, t, lead)]) VOICING = {} # per phrase, voiced runs in beats — vowels vs consonants +# TAKECHARTS — a chart per take, not one chart lent around. +# @jeffrey: "our envelopes etc are still fitting like the original samples · +# we need to like restart the whole process for each actual take · or it +# will sound wonky". bin/takechart.py assembles a take's line from its +# per-word corpus files and measures its OWN onsets, syllable seams and +# notes; it keeps only `durs` from w-whole-line, because unit lengths in +# beats are the song and everything else in that entry is f- on one day. +# Registering the result here rather than warping afterwards is the whole +# point: the take then goes through this file's real pipeline — consonant +# runway, boundary snap, energy trim, note re-measurement, THE HOLD, +# nervox, the sibilant restore — and gets an envelope of its own. +# OPT-IN. These are a BENCH, not the record — @jeffrey: "sounds bad i think +# we should stick to our original". Registered unconditionally they would +# join every bare halo3 run, get built into the bank, and be loaded as +# samples by an engine that never asks for them. bin/tryout-takes.sh sets +# TAKES=1; nothing else does, so the record's pipeline is untouched. +_takes_path = os.path.join(LANE, "samples", ".takecharts.json") +if os.environ.get("TAKES") and os.path.exists(_takes_path): + _takes = json.load(open(_takes_path)) + for _name, _r in _takes.items(): + SLICES[_r["chart"]["slice"]] = _r["slice"] + ALIGN[_r["chart"]["slice"]] = _r["align"] + _c = dict(_r["chart"]) + for _k in ("durs", "times"): + _c[_k] = {int(_i): _v for _i, _v in (_c.get(_k) or {}).items()} + _c["sylls"] = {int(_i): [(None if _c0 is None else float(_c0), _l) + for _c0, _l in _cuts] + for _i, _cuts in (_c.get("sylls") or {}).items()} + CHART[_name] = _c + print(f"→ .takecharts.json registered {len(_takes)} take(s): " + f"{' '.join(sorted(_takes))}") + +# CHART-EDITS — what ChartWizard dragged. The CHART literal above stays the +# score, with its reasons written next to every number; the GUI writes only +# the numbers, into a sidecar merged over the top. Two authors, one file +# each, so a drag can never eat a paragraph explaining why a boundary is +# where it is — and `git diff chart-edits.json` is a readable list of what +# a session moved by hand. +_edits_path = os.path.join(LANE, "chart-edits.json") +if os.path.exists(_edits_path): + _edits = json.load(open(_edits_path)) + for _name, _e in _edits.items(): + if _name not in CHART: + continue + _ch = CHART[_name] + for _k in ("times", "durs", "gaps", "stretch"): + if _k in _e: + _ch[_k] = {**(_ch.get(_k) or {}), + **{int(_i): _v for _i, _v in _e[_k].items()}} + if "sylls" in _e: # [[null|seconds, label], …] + _ch["sylls"] = {**(_ch.get("sylls") or {}), + **{int(_i): [(None if _c[0] is None else float(_c[0]), _c[1]) + for _c in _cuts] + for _i, _cuts in _e["sylls"].items()}} + if "end" in _e: + _ch["end"] = _e["end"] + print(f"→ chart-edits.json merged over {len(_edits)} phrase(s)") + ONLY = {p for p in os.environ.get("PHRASES", "").split(",") if p} LEAD_ONLY = os.environ.get("LEAD_ONLY") is not None @@ -891,12 +1252,20 @@ # labelled a second late means the word BEFORE it swallows it whole, # which is the extra syllable heard inside "for". These are read off # her own onsets in the source and pinned. aligned = slice_name in ALIGN + # PROVENANCE. Every unit's left edge is owned by exactly one knob in + # the CHART, and ChartWizard has to write a drag back to that knob and + # no other: `pin` is the pre-split word index, `cut` is None for the + # word's own start (times[pin]) or k for its k-th syllable cut + # (sylls[pin][k-1]). The fricative sub-split makes a ·b edge that no + # knob owns — halo3 finds it in the audio — so it carries cut="auto" + # and the GUI refuses to drag it. if aligned: words = [dict(t=w["t"], start=t0_slice + w["start"], end=t0_slice + w["end"], f0_hz=w["f0_hz"], - note=w["note"]) for w in ALIGN[slice_name]["words"]] + note=w["note"], pin=i, cut=None) + for i, w in enumerate(ALIGN[slice_name]["words"])] else: - words = list(entry["word_f0"]) + words = [dict(w, pin=i, cut=None) for i, w in enumerate(entry["word_f0"])] for wi, ts in (ch.get("times") or {}).items(): if 0 <= wi < len(words): words[wi]["start"] = t0_slice + ts @@ -918,7 +1287,8 @@ head = next((c[1] for c in cuts if c[0] is None), base["t"]) cuts = [c for c in cuts if c[0] is not None] edges = [base["start"]] + [t0_slice + c[0] for c in cuts] + [base["end"]] labels = [head] + [c[1] for c in cuts] - words[wi:wi + 1] = [dict(base, start=edges[k], end=edges[k + 1], t=labels[k]) + words[wi:wi + 1] = [dict(base, start=edges[k], end=edges[k + 1], + t=labels[k], pin=wi, cut=(None if k == 0 else k)) for k in range(len(labels))] syll_pins.update(labels[1:]) # a measured cut is a measurement too @@ -940,7 +1310,17 @@ for ui in sorted(ch.get("splits", []), reverse=True): w = words[ui] f0 = int(round((w["start"] - t0_slice) / FRAME_S)) f1 = int(round((w["end"] - t0_slice) / FRAME_S)) - lo, run, split_f = f0 + max(3, (f1 - f0) // 4), 0, None + # AN ONSET CONSONANT IS NOT AN INTERNAL ONE. The search used to + # start a quarter of the way into the unit, which was fine while + # "sitting" began at its vowel — once the block reached back to + # take her 220 ms /s/, that quarter-point landed INSIDE the + # sibilant and split sit·ting 110 ms early, inside the first + # syllable. Skip the word's own opening unvoiced run first, then + # look a quarter of the way through what is left. + v0 = f0 + while v0 < f1 - 1 and v0 < len(a["voiced"]) and not a["voiced"][v0]: + v0 += 1 + lo, run, split_f = v0 + max(3, (f1 - v0) // 4), 0, None for f in range(lo, min(f1, len(a["voiced"]))): if not a["voiced"][f]: run += 1 @@ -953,7 +1333,7 @@ if split_f is None: split_f = (f0 + f1) // 2 ts = t0_slice + split_f * FRAME_S first = dict(w, end=ts, t=w["t"] + "·a") - second = dict(w, start=ts, t=w["t"] + "·b") + second = dict(w, start=ts, t=w["t"] + "·b", cut="auto") words[ui:ui + 1] = [first, second] # RE-MEASURE THE NOTE. f0_hz came from the aligner, over the span the # aligner thought the word had. Once `times` repins a boundary or a @@ -983,10 +1363,19 @@ unit_src.append((max(0, s0), min(F, max(s0 + 1, s1)))) unit_src, trims, rest_src = trim_units(x, fs, unit_src, [w["t"] for w in words]) unit_src = keep_attacks(unit_src, rest_src, x, fs) + # ONE CLOCK. `end` used to subtract the slice offset while `times` and + # `sylls` add it, so an `end` written in the same seconds you read off + # the zoom landed 280 ms early — @jeffrey: "i can't hear the s in + # pass". Her /s/ is 24.03–24.30 and the cap was falling at 23.97, in + # the gap before it, so the sibilant was cut every render. It is the + # slice's clock now, like every other time in this chart. if ch.get("end"): # the last word stops at the cap too - cap = int(round((ch["end"] - t0_slice) / FRAME_S)) - a0, b0_ = unit_src[-1] - unit_src[-1] = (a0, min(b0_, max(a0 + 1, cap))) + # …and it SETS the last unit's end rather than only clipping it. + # The aligner stopped "pass" at 24.20, inside her /s/, and a cap + # that can only shorten could never give the rest back. + cap = int(round(ch["end"] / FRAME_S)) + a0, _ = unit_src[-1] + unit_src[-1] = (a0, min(F, max(a0 + 1, cap))) gapsb = [ch.get("gaps", {}).get(i, 0.0) for i in range(len(ch["units"]))] idx, holds, fade, Z, ants, rise, rests = build_warp( @@ -997,9 +1386,82 @@ int(round((ch["end"] - t0_slice) / FRAME_S)) if ch.get("end") else None) f0_o = a["f0c"][idx].copy() voiced_o = a["voiced"][idx] - # THE HOLD — long stretches flatten to the unit's median grid tone + # THE MELODY LOCK — another take, HER tune. + # @jeffrey: "whoa the pitches are way off now". A take chart keeps the + # composition and re-measures the performance, and the first cut of it + # counted only `durs` as composition. But the snap regulates a voice + # toward the nearest degree of the A#-minor grid, not toward a NOTE — + # so with its own notes re-measured, every take sang its own tune, in + # its own octave. Melody is the song exactly as much as rhythm is. + # + # Each unit is moved onto the spine's semitone by an OFFSET rather than + # by rewriting f0 flat, so the take keeps its own vibrato, scoops and + # glides inside the note and only the note itself is hers. The line is + # folded by WHOLE OCTAVES to wherever the take actually sings — several + # of these voices sit an octave below her — because forcing her + # register on a low voice is a different song, not the same one. + # + # THE OFFSET IS A CURVE, NOT A STAIRCASE. The first version multiplied + # each unit by a constant and stopped there — @jeffrey: "it sounds so + # glitchy". It did: the pitch stepped instantly at every unit boundary, + # by up to several semitones, and WORLD renders a hard f0 step as a + # click. rq came out with 425 frames jumping more than 2 st against the + # spine's 132. So the offsets are laid on a per-frame track and + # smoothed with the same window the snap uses — which is why a real + # melodic leap survives: it is the CORRECTION that is smoothed, and the + # octave jump on "of" lives in the take's own contour underneath. + melody = ch.get("melody") + locked = None + if melody and len(melody) == len(ch["units"]): + want, have = np.array(melody, dtype=float), np.full(len(melody), np.nan) + bounds = [] + for u, (bt, du) in enumerate(ch["units"]): + o0 = Z + int(round(bt * SPB / FRAME_S)) + o1 = Z + int(round((bt + du) * SPB / FRAME_S)) + o0, o1 = max(0, o0), min(len(f0_o), o1) + bounds.append((o0, o1)) + seg = f0_o[o0:o1][voiced_o[o0:o1]] + seg = seg[seg > 0] + if len(seg): + have[u] = 12.0 * np.log2(float(np.median(seg)) / TONIC) + ok = ~np.isnan(have) + if ok.any(): + octs = round(float(np.median((have - want)[ok])) / 12.0) + locked = want + 12.0 * octs + # a unit with no usable voiced median gets its neighbours' + # correction rather than a cliff back to zero + delta_u = np.where(ok, locked - have, np.nan) + idxs = np.arange(len(delta_u)) + delta_u = np.interp(idxs, idxs[ok], delta_u[ok]) + track = np.zeros(len(f0_o)) + for u, (o0, o1) in enumerate(bounds): + if o1 > o0: + track[o0:o1] = delta_u[u] + if bounds: + track[:bounds[0][0]] = delta_u[0] + track[bounds[-1][1]:] = delta_u[-1] + track = smooth(track, int(SMOOTH_MS / FRAME_MS)) + f0_o = np.where(voiced_o, f0_o * 2.0 ** (track / 12.0), 0.0) + print(f" melody locked: {int(ok.sum())}/{len(want)} units onto the " + f"spine, {octs:+d} octave{'' if abs(octs) == 1 else 's'}, " + f"median move {np.median(np.abs(delta_u)):.1f} st") + + # THE HOLD — long stretches flatten to the unit's median grid tone. + # It reads the SOURCE analysis, which is right for the take the chart + # was measured from and wrong for any other: with a melody lock in + # front of it, every held note was being flattened back onto the pitch + # the singer originally sang and the lock silently undone. That is why + # rq's seven bad units were all its LONG ones, and why "of" — the one + # octave leap in the lyric — came out 16 semitones under the chart. + # Where the melody is locked, the hold sustains the note as it will be + # SUNG. Without a lock it reads the source exactly as before, so the + # spine is untouched. for (o0, o1, s0, s1) in holds: - seg = a["f0c"][s0:s1][a["voiced"][s0:s1]] + if locked is not None: + seg = f0_o[o0:o1][voiced_o[o0:o1]] + seg = seg[seg > 0] + else: + seg = a["f0c"][s0:s1][a["voiced"][s0:s1]] if not len(seg): continue med = np.median(seg) @@ -1031,7 +1493,15 @@ if o1 > o0: f0_o[o0:o1] *= 2.0 ** (semis / 12.0) renders = {} - out, _ = synth_from(a, idx, f0_o, fade=fade, rise=rise, rests=rests) + # NERVOX — @jeffrey: "i think wavering notes too / flanging and wiggling + # the pitches · so the voice sounds more nervous · lets call this + # 'nervox' technique". The snap is what makes her notes NOTES; this is + # what stops them being a machine's notes. Held frames only — the same + # glide test the snap uses, so the two never fight. pop/lib/nervox.py. + rate_o = a["rate"][idx] + f0_n = nervox_waver(f0_o, FRAME_S, rate=rate_o, voiced=voiced_o) + out, _ = synth_from(a, idx, f0_n, fade=fade, rise=rise, rests=rests) + out = nervox_flange(out, a["fs"]) sf.write(os.path.join(VOX4, f"{name}.wav"), out, fs) renders["lead"] = round(len(out) / fs, 3) @@ -1081,12 +1551,27 @@ k = j else: k += 1 - notes = [] + # WHICH LYRIC WORD IS THIS UNIT. The chart plays 24 units but the + # lyric has 18 words — "patiently" is three units, "sitting" and + # "myself" and "waiting" and "very" are two each. Anything warping a + # DIFFERENT take onto this chart has to know that grouping, or it + # maps 18 source words onto 24 slots by index and sings six of them + # twice. Both split mechanisms mark a continuation with `cut`, so a + # unit opens a new word exactly when `cut` is None. + notes, wi = [], -1 for u, (wd, (beat, durb)) in enumerate(zip(words, ch["units"])): - st = int(np.round(12.0 * np.log2(wd["f0_hz"] / TONIC))) if wd["f0_hz"] else 0 + if wd.get("cut") is None: + wi += 1 + # what the band doubles is what the voice SINGS — the locked note + # where there is one, the measured note otherwise. + if locked is not None: + st = int(round(locked[u])) + else: + st = int(np.round(12.0 * np.log2(wd["f0_hz"] / TONIC))) if wd["f0_hz"] else 0 st += int((ch.get("shift") or {}).get(u, 0)) notes.append((beat, durb, st, wd["t"].strip(), - round(ants[u] * FRAME_S / SPB, 4) if u < len(ants) else 0.0)) + round(ants[u] * FRAME_S / SPB, 4) if u < len(ants) else 0.0, + wi)) chart_c.append((name, lead_in, beats_total, notes)) VOICING[name] = voiced_runs # THE SPANS ACTUALLY PLAYED — after times, sylls, snapping, attack @@ -1098,8 +1583,9 @@ # alignment use — adding the source offset here silently shifted the # audit against the audio it was checking. played = [[w["t"], round(a_ * FRAME_S, 3), round(b_ * FRAME_S, 3)] for w, (a_, b_) in zip(words, unit_src)] + pins = [dict(t=w["t"], pin=w.get("pin"), cut=w.get("cut")) for w in words] manifest[name] = dict(slice=slice_name, lead_in=round(lead_in, 3), - spans=played, + spans=played, pins=pins, beats=beats_total, renders=renders, snaps=snaps, trims=trims, words=entry["words"]) print(f" {name:22s} {renders['lead']:5.2f}s lead·8ve×2·low3·low5 «{entry['words']}»") @@ -1110,8 +1596,8 @@ print(f" trimmed: {' · '.join(trims)}") _new_chart = dict(_old_chart) _new_chart.update({name: dict(leadIn=round(li, 3), beats=bt, voiced=VOICING[name], - notes=[dict(beat=b, dur=d, st=s, t=t, lead=ld) - for (b, d, s, t, ld) in ns]) + notes=[dict(beat=b, dur=d, st=s, t=t, lead=ld, w=wi) + for (b, d, s, t, ld, wi) in ns]) for (name, li, bt, ns) in chart_c}) json.dump(manifest, open(os.path.join(VOX4, ".manifest.json"), "w"), indent=1) @@ -1128,19 +1614,21 @@ "", f"#define CHART_BPM {BPM}", f"#define CHART_TONIC {TONIC}", "", - "typedef struct { double beat, dur; int st; } ChartNote;", + "// `t` is the unit's label — the C addresses a word by name so a", + "// treatment can be written against \"pa\" rather than against unit 17.", + "typedef struct { double beat, dur; int st; const char *t; } ChartNote;", "typedef struct { const char *name; double leadIn; double beats;", " int n; const ChartNote *notes; } ChartPhrase;", "", ] _all = [(nm, _new_chart[nm]["leadIn"], _new_chart[nm]["beats"], - [(q["beat"], q["dur"], q["st"], q["t"], q.get("lead", 0.0)) - for q in _new_chart[nm]["notes"]]) for nm in _new_chart] + [(q["beat"], q["dur"], q["st"], q["t"], q.get("lead", 0.0), q.get("w", i)) + for i, q in enumerate(_new_chart[nm]["notes"])]) for nm in _new_chart] for name, lead_in, beats_total, notes in _all: ident = name.replace("-", "_") lines.append(f"static const ChartNote {ident}_notes[] = {{") - for (beat, durb, st, _t, _lead) in notes: - lines.append(f" {{ {beat:.2f}, {durb:.2f}, {st} }},") + for (beat, durb, st, _t, _lead, _w) in notes: + lines.append(f' {{ {beat:.2f}, {durb:.2f}, {st}, "{_t}" }},') lines.append("};") lines.append("") lines.append("static const ChartPhrase CHART[] = {") diff --git a/pop/loner/bin/singdub.py b/pop/loner/bin/singdub.py new file mode 100644 --- /dev/null +++ b/pop/loner/bin/singdub.py @@ -0,0 +1,397 @@ +# singdub.py — make a translated line SING her melody. +# +# @jeffrey: "i wanna hear the other langs being sung with the beat · in the +# mix". +# +# bin/dub.py returns the translation SPOKEN in her voice. Spoken is not a +# verse: it has its own prosody, its own length, and no relationship to the +# bar. This puts it on the chart — the same 60-beat melody, note for note, +# that halo3 warps her English take onto. +# +# The move is f0-replace ([[pop-world-autotune]]), not pitch correction: +# the spoken line's own contour is discarded and the CHART's semitone is +# written in its place, because the point is her tune, not the carrier's +# intonation. What survives from the recording is the part that carries the +# language — the formants, the consonants, the aperiodicity. +# +# MAPPING. Her line is 24 charted units; a translation has a different +# number of syllables in a different order, so a word-for-word mapping does +# not exist and pretending otherwise is how you get gibberish on the beat. +# Instead the spoken line is split into VOICED RUNS (its own syllable +# nuclei, found in the audio) and those runs are distributed across the +# chart's notes proportionally. A language with more syllables than she has +# notes puts several syllables inside one note — which is melisma's +# opposite and exactly what a translated verse does. +# +# pop/.venv/bin/python pop/loner/bin/singdub.py fr es da ru hi +# → vox-dub/sung-.wav, one phrase long, starting at beat 0 + +import json, os, subprocess, sys, tempfile +import numpy as np +import soundfile as sf +import pyworld as pw + +HERE = os.path.dirname(os.path.abspath(__file__)) +LANE = os.path.dirname(HERE) +sys.path.insert(0, HERE) +sys.path.insert(0, os.path.join(os.path.dirname(LANE), "lib")) +from nervox import waver as nervox_waver, flange as nervox_flange + +TONIC = 237.0 +BPM = 122.0 +SPB = 60.0 / BPM +FRAME_MS = 5.0 +FRAME_S = FRAME_MS / 1000.0 +GATE_DB = -34.0 +MIN_RUN_S = 0.070 +GLIDE_S = 0.055 # how long f0 takes to arrive at a new note +VALLEY = 0.55 # an energy dip this deep is a syllable boundary + +# THE STRETCH IS NOT UNIFORM. halo3 warps her English this way and singdub +# has to as well — @jeffrey: "we need better durations / syllable checking · +# consonsnant / vowerl stretching · it feels broken". A vowel can be held +# for a whole bar and still sound like the vowel; a consonant held for a +# whole bar is a smear. So the slot's extra time is spent almost entirely +# on voiced frames, and consonants ride near their natural length. +W_VOWEL = 1.0 +W_CONS = 0.18 +HOLD_RATIO = 2.2 # past this, sustain the vowel instead of stretching + + +def ratio_cap(r): + """How much a CONSONANT may be slowed even inside a held note.""" + return min(r, 1.6) + + +def load_mp3(path): + """No mp3 decoder in soundfile — go through ffmpeg.""" + tmp = tempfile.mktemp(suffix=".wav") + subprocess.run(["ffmpeg", "-y", "-v", "error", "-i", path, + "-ac", "1", "-ar", "44100", tmp], check=True) + x, fs = sf.read(tmp, dtype="float64") + os.unlink(tmp) + return x, fs + + +def voiced_runs(x, fs, f0): + """Syllable nuclei, straight from the audio. + + Splitting on unvoiced gaps ALONE is not enough and French proved it: + "recroquevillée en moi-même" is continuously voiced, so the whole + phrase came back as one run, got assigned to one note, and the words + inside it were stretched into mush — @jeffrey heard it immediately. + A voiced run is therefore cut again at its energy VALLEYS, which is + where one syllable hands over to the next in a legato language. + """ + n = int(round(fs * FRAME_S)) + m = min(len(f0), len(x) // n) + rms = np.sqrt((x[:m * n].reshape(m, n) ** 2).mean(axis=1)) + gate = (np.max(np.abs(x)) or 1.0) * 10.0 ** (GATE_DB / 20.0) + on = (rms > gate) & (f0[:m] > 0) + + gross, k = [], 0 + while k < m: + if on[k]: + j = k + while j < m and on[j]: + j += 1 + if (j - k) * FRAME_S >= MIN_RUN_S: + gross.append((k, j)) + k = j + else: + k += 1 + + # smooth the envelope, then cut at every dip that is a real valley: + # deep enough against BOTH neighbouring peaks, and far enough from the + # last cut to be a syllable rather than a wobble. + w = max(1, int(round(0.030 / FRAME_S))) + env = np.convolve(rms, np.ones(w) / w, mode="same") + minsep = int(round(MIN_RUN_S / FRAME_S)) + runs = [] + for (a, b) in gross: + cuts = [a] + i = a + minsep + while i < b - minsep: + lo = env[i] + left = env[cuts[-1]:i].max() if i > cuts[-1] else lo + right = env[i:min(b, i + 2 * minsep)].max() + if lo < VALLEY * min(left, right) and lo == env[i - minsep // 2:i + minsep // 2].min(): + cuts.append(i) + i += minsep + else: + i += 1 + cuts.append(b) + runs += [(u, v) for u, v in zip(cuts[:-1], cuts[1:]) if v - u >= minsep // 2] + return runs, m + + +# THE LYRIC, in order. bin/takes.py indexed every utterance across nineteen +# takes and ten of them have all eighteen of these words on their own — so +# a whole line can be BUILT from a take rather than sliced out of one, with +# boundaries that are exact instead of transcribed. +LYRIC = ("sitting curled up in myself i think of a stone just waiting " + "very patiently for time to pass").split() +CORPUS_GAP_S = 0.06 # a breath between words, so they do not run together + + +def corpus_line(take): + """One take's whole line, assembled from its per-word corpus files. + + @jeffrey: "i guess we could try and map out other takes and see how + they sound solo". This is the cheap way in. singdub's other sources — + a scribed dub, an energy-detected spoken line — both GUESS where the + words are; samples/corpus is already cut per word, so the spans it + returns are measured, and any take that owns all eighteen words can be + charted without a transcription step at all. + """ + d = os.path.join(LANE, "samples", "corpus") + if not os.path.isdir(d): + return None + idx = {} + for f in os.listdir(d): + if not f.endswith(".wav") or f.count("-") < 2: + continue + tk, _, w = f[:-4].split("-", 2) + if tk == take: + idx[w] = os.path.join(d, f) + if any(w not in idx for w in LYRIC): + return None + parts, spans, fs, n = [], [], None, 0 + for w in LYRIC: + y, fs = sf.read(idx[w], dtype="float64") + if y.ndim > 1: + y = y.mean(axis=1) + spans.append((n / fs, (n + len(y)) / fs)) + parts.append(y) + n += len(y) + gap = np.zeros(int(CORPUS_GAP_S * fs)) + parts.append(gap) + n += len(gap) + return np.concatenate(parts), fs, spans, list(LYRIC) + + +def main(): + langs = sys.argv[1:] or ["fr"] + chart = json.load(open(os.path.join(LANE, "vox4", ".chart.json")))["w-whole-line"] + notes = chart["notes"] + total_beats = chart["beats"] + + for lang in langs: + # `lang` may name a TAKE instead of a translation. @jeffrey: "lets + # work on swap lead and also use / bring in group takes · but the + # idea is we start small with camille's softest take then we build + # up each one". Putting another take on the chart is the same job + # as putting another language on it — different words in, her + # melody out — so s-whole-line and the ensemble o-whole-line go + # through this path rather than needing their own hand-pinned + # chart, which is a session's work each. + built = corpus_line(lang) + take = os.path.join(LANE, "samples", f"{lang}.wav") + src = os.path.join(LANE, "vox-dub", f"sts-{lang}.mp3") + if built: + x, fs, corpus_spans, corpus_labels = built + else: + corpus_spans = None + if os.path.exists(take): + src = take + elif not os.path.exists(src): + src = os.path.join(LANE, "vox-dub", f"spoken-{lang}.mp3") + if not os.path.exists(src): + print(f" {lang}: no corpus take, no samples/{lang}.wav, " + f"nothing in vox-dub/") + continue + if src.endswith(".wav"): + x, fs = sf.read(src, dtype="float64") + if x.ndim > 1: + x = x.mean(axis=1) + else: + x, fs = load_mp3(src) + + f0r, t = pw.harvest(x, fs, f0_floor=80.0, f0_ceil=600.0, frame_period=FRAME_MS) + f0 = pw.stonemask(x, f0r, t, fs) + fft = pw.get_cheaptrick_fft_size(fs, f0_floor=80.0) + sp = pw.cheaptrick(x, f0, t, fs, fft_size=fft, f0_floor=80.0) + ap = pw.d4c(x, f0, t, fs, fft_size=fft) + # PREFER THE WORDS. @jeffrey: "per language we should be able to map + # the shape of the words etc". dub.py scribe returns this language's + # real word spans, so the verse is charted word by word the way the + # English one is; the energy detector below is only the fallback for + # a language that has not been scribed yet. + wpath = os.path.join(LANE, "vox-dub", ".words.json") + words = json.load(open(wpath)).get(lang) if os.path.exists(wpath) else None + if corpus_spans: + runs = [(int(a_ / FRAME_S), int(b_ / FRAME_S)) + for (a_, b_) in corpus_spans] + labels = corpus_labels + src_kind = "corpus words" + elif words: + runs = [(int(w["start"] / FRAME_S), int(w["end"] / FRAME_S)) + for w in words] + runs = [(a_, b_) for (a_, b_) in runs if b_ > a_] + labels = [w["t"] for w in words] + src_kind = "words" + else: + runs, _m = voiced_runs(x, fs, f0) + labels = [f"~{i}" for i in range(len(runs))] + src_kind = "syllables" + if not runs: + print(f" {lang}: nothing to map"); continue + + # the output timeline: one phrase, on the grid + out_frames = int(round(total_beats * SPB / FRAME_S)) + idx = np.zeros(out_frames, dtype=int) + st_out = np.full(out_frames, np.nan) + ratios = [] # so a bad duration is visible, not just audible + + # distribute this language's syllables across her notes + # EVERY NOTE GETS A WORD. Mapping word→note leaves notes empty + # whenever a language has fewer words than she has notes — French + # left seven silent, Russian nine, and a melody with holes in it is + # not her melody. Mapping note→word instead guarantees coverage: a + # language with fewer words simply holds one across several notes, + # which is what a singer does with a long line and few syllables. + R = len(runs) + buckets = [[] for _ in notes] + nwords = max(nt.get("w", k) for k, nt in enumerate(notes)) + 1 + if R == nwords: + # THE SAME LYRIC, A DIFFERENT TAKE. This chart plays 24 units + # but the lyric is 18 words — "patiently" is three units, + # "sitting" and "myself" and "waiting" and "very" are two + # each. The index spread below is for TRANSLATIONS, where the + # word counts genuinely differ and holding one word across + # several notes is what a singer would do. Run it on another + # take of the same words and `k * 18 // 24` hands words 0, 3, + # 6, 9, 12 and 15 to two adjacent notes apiece — @jeffrey: + # "the second run of samples around 1:10 is all fucked up". + # It was: six words sung twice, then flattened by THE HOLD. + # + # When the counts match, the mapping is known exactly. Each + # word goes to ITS units, and a word spanning several units is + # CUT between them rather than repeated — proportionally by + # note length, then nudged onto the nearest unvoiced frame, + # because the seam inside "pa|tient|ly" is the /t/. + by_word = {} + for k, nt in enumerate(notes): + by_word.setdefault(nt.get("w", k), []).append(k) + for w, ks in sorted(by_word.items()): + u, v = runs[w] + durs = [notes[k]["dur"] for k in ks] + tot = sum(durs) or 1.0 + edges, acc = [u], 0.0 + for d in durs[:-1]: + acc += d + e = u + int(round((v - u) * acc / tot)) + # snap to a consonant: search ±12% of the word for a + # frame she is not voicing + win = max(2, int(0.12 * (v - u))) + cand = [f for f in range(max(u + 1, e - win), + min(v - 1, e + win)) + if f < len(f0) and f0[f] <= 0] + if cand: + e = min(cand, key=lambda f: abs(f - e)) + edges.append(max(edges[-1] + 1, e)) + edges.append(max(edges[-1] + 1, v)) + for j, k in enumerate(ks): + buckets[k] = [(edges[j], edges[j + 1])] + print(f" {lang}: same lyric — {R} words → {len(notes)} units, " + f"{len(notes) - R} syllable cuts") + else: + for k in range(len(notes)): + buckets[k].append(runs[min(R - 1, k * R // len(notes))]) + + for k, nt in enumerate(notes): + a = int(round(nt["beat"] * SPB / FRAME_S)) + b = int(round((nt["beat"] + nt["dur"]) * SPB / FRAME_S)) + a, b = max(0, a), min(out_frames, b) + if b <= a: + continue + group = buckets[k] + if not group: # nobody sings here — hold the + idx[a:b] = idx[a - 1] if a else 0 # previous frame, silently + continue + # this bucket's source frames… + srcf = np.concatenate([np.arange(u, v) for (u, v) in group]) + # …warped through a WEIGHTED clock, so the slot's extra time is + # spent on vowels and the consonants keep their own length. + wts = np.where(f0[srcf] > 0, W_VOWEL, W_CONS) + cum = np.concatenate([[0.0], np.cumsum(wts)]) + cum /= cum[-1] + pos = np.interp((np.arange(b - a) + 0.5) / (b - a), + cum, np.arange(len(cum), dtype=float)) - 0.5 + + # THE HOLD. A spoken syllable is ~0.15 s and one of her notes is + # up to 2 s, so the honest stretch is 10–30x — and marching + # through a syllable twenty times too slowly is a slur, not a + # held note. Past HOLD_RATIO the syllable stops being stretched + # and its VOWEL is sustained instead: the frame index dwells + # around the vowel's centre, drifting slowly so the spectrum + # keeps evolving rather than freezing into a buzz. Consonants + # are untouched — they still play once, at their own speed. + ratio = (b - a) / max(1, len(srcf)) + if ratio > HOLD_RATIO: + vi = np.where(f0[srcf] > 0)[0] + if len(vi) >= 3: + c0, c1 = vi[0], vi[-1] + head = int(c0 / max(ratio_cap(ratio), 1e-6)) + tail = int((len(srcf) - 1 - c1) / max(ratio_cap(ratio), 1e-6)) + n_out = b - a + head = min(head, n_out // 4) + tail = min(tail, n_out // 4) + body = max(1, n_out - head - tail) + mid, span = 0.5 * (c0 + c1), max(1.0, (c1 - c0) * 0.5) + # a slow triangle through the vowel — never the same + # frame twice in a row, never outside the vowel + ph = np.linspace(0, body / (0.55 / FRAME_S), body) + drift = mid + span * (2.0 / np.pi) * np.arcsin(np.sin(ph)) + pos = np.concatenate([ + np.linspace(0, c0, head, endpoint=False) if head else np.zeros(0), + drift, + np.linspace(c1, len(srcf) - 1, tail) if tail else np.zeros(0), + ])[:n_out] + if len(pos) < n_out: + pos = np.pad(pos, (0, n_out - len(pos)), mode="edge") + idx[a:b] = srcf[np.clip(np.round(pos).astype(int), 0, len(srcf) - 1)] + st_out[a:b] = nt["st"] + ratios.append((nt["t"], len(group), len(srcf) * FRAME_S, + (b - a) * FRAME_S)) + + # HER MELODY, written over the carrier's intonation. Glide into each + # new note instead of stepping — a step reads as a splice. + st_f = st_out.copy() + last = st_f[~np.isnan(st_f)][0] if np.any(~np.isnan(st_f)) else 0.0 + g = max(1, int(GLIDE_S / FRAME_S)) + for i in range(out_frames): + if np.isnan(st_f[i]): + st_f[i] = last + else: + last = st_f[i] + sm = np.convolve(st_f, np.ones(g) / g, mode="same") + f0_new = TONIC * 2.0 ** (sm / 12.0) + voiced_o = f0[idx] > 0 + f0_new = np.where(voiced_o, f0_new, 0.0) + f0_new = nervox_waver(f0_new, FRAME_S, voiced=voiced_o) + + y = pw.synthesize(f0_new, sp[idx].copy(order="C"), ap[idx].copy(order="C"), + fs, frame_period=FRAME_MS) + y = nervox_flange(y, fs) + pk = np.max(np.abs(y)) or 1.0 + y = y / pk * 0.85 + + dest = os.path.join(LANE, "vox-dub", f"sung-{lang}.wav") + sf.write(dest, y, fs) + # SYLLABLE CHECKING. A note holding four syllables, or one stretched + # 4x, is where a translated verse turns to mush — print it rather + # than wait to hear it. + worst = sorted(ratios, key=lambda r: -(r[3] / max(r[2], 1e-6)))[:3] + empty = len(notes) - len(ratios) + crowd = max((r[1] for r in ratios), default=0) + print(f" ✓ {lang}: {dest} {len(y) / fs:.1f}s · {R} syllables over " + f"{len(notes)} notes · {empty} notes empty · " + f"up to {crowd} syllables in one note") + for t, ns, src_s, slot_s in worst: + print(f" {t:>8} {ns} syll {src_s:.2f}s → {slot_s:.2f}s " + f"{slot_s / max(src_s, 1e-6):.2f}x") + + +if __name__ == "__main__": + main() diff --git a/pop/loner/bin/stage-takes.sh b/pop/loner/bin/stage-takes.sh new file mode 100644 --- /dev/null +++ b/pop/loner/bin/stage-takes.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +# stage-takes.sh — level-match every lead take before it enters the engine. +# +# @jeffrey: "i think we need to master / treat each vocal separate right?" +# Right. The three takes were recorded in three rooms at three distances: +# f- lands at −22.1 LUFS raw, s- at −16.8, o- (the group) at −12.2. Warping +# them onto the chart does not fix that — it carries it. Dropping them into +# the arrangement at hand-picked gains means every gain has to be re-guessed +# whenever a take is re-rendered. +# +# So each take is MEASURED and moved by ONE static dB to a common integrated +# loudness, exactly the way the lane masters a mix. After this, a gain in +# lonerremix.c means the same thing whichever take it is applied to, and the +# swap is a change of ROOM rather than a change of level. +set -euo pipefail +LANE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +# THE REFERENCE IS THE SPINE. f- is the take that was charted by hand, word +# by word; the others are warped onto ITS chart. So it sets the level too, +# rather than all three being moved to some outside number that would drift +# the moment halo3.py re-renders. +lufs() { ffmpeg -hide_banner -nostats -i "$1" -af ebur128 -f null - 2>&1 \ + | awk '/I:/{v=$2} END{print v}'; } +peak() { ffmpeg -hide_banner -nostats -i "$1" -af volumedetect -f null - 2>&1 \ + | awk -F': ' '/max_volume/{gsub(/ dB/,"",$2); print $2}'; } + +TARGET="${TARGET:-$(lufs "$LANE/vox4/w-whole-line.wav")}" + +stage() { # stage + local src="$1" dest="$LANE/vox4/$2.wav" + local i g + i=$(lufs "$src") + # THE LANE'S MASTERING LAW, on one voice: MEASURE → one static dB → true- + # peak limiter. Clamping the static gain instead — taking the smaller of + # the loudness move and whatever kept the peak at −1 — sounds safe and is + # not: a take with sharp word onsets (the corpus lines are cut per word, + # so every word starts with one) loses the whole match. try-pf wanted + # +6.0 dB, the clamp allowed +0.4, and it arrived nearly 6 dB under the + # take it was being compared against. A limiter catching the top few dB + # of a sparse vocal is far less of a change than that. + g=$(awk -v i="$i" -v t="$TARGET" 'BEGIN{printf "%.2f", t-i}') + # PCM_16, matching what halo3 writes into the bank. The C loader reads + # anything, but bin/timeline.py draws its waveform through the stdlib + # `wave` module and that refuses float ("unknown format: 3") — which + # killed the whole audition batch after the first take. + ffmpeg -y -v error -i "$src" \ + -af "volume=${g}dB,alimiter=limit=0.891:attack=4:release=60:level=disabled" \ + -c:a pcm_s16le "$dest" + printf " %-12s %8s LUFS → %+6s dB → %s LUFS, peak %s dB\n" \ + "$2" "$i" "$g" "$(lufs "$dest")" "$(peak "$dest")" +} + +# stage-takes.sh stages exactly that one and stops — +# bin/tryout-takes.sh uses this to bench a take without touching the record. +if [ $# -eq 2 ]; then + echo "→ level-matching $2 to the f- spine ($TARGET LUFS)" + stage "$1" "$2" + exit 0 +fi + +echo "→ level-matching leads to the f- spine ($TARGET LUFS)" +stage "$LANE/vox-dub/sung-s-whole-line.wav" alt-soft +# THE GROUP TAKE IS NOT STAGED. o-whole-line is Camille, @jeffrey and Alex +# together, and @jeffrey: "lets not do the group vocals anymore · they are +# weird". The chart is one pitch contour and singdub f0-REPLACES the take +# with it — fine for a solo, where harvest tracks one larynx cleanly, but +# three voices singing slightly apart give an f0 estimate that flickers +# between whoever is loudest, and the warp smears the ensemble into one +# synthetic voice. To use that take it would have to be PLACED as a +# performance rather than resynthesised: +# stage "$LANE/vox-dub/sung-o-whole-line.wav" alt-group diff --git a/pop/loner/bin/takechart.py b/pop/loner/bin/takechart.py new file mode 100644 --- /dev/null +++ b/pop/loner/bin/takechart.py @@ -0,0 +1,230 @@ +# takechart.py — give a take its OWN chart, instead of borrowing hers. +# +# @jeffrey: "our envelopes etc are still fitting like the original samples · +# we need to like restart the whole process for each actual take · or it +# will sound wonky". +# +# He is right, and it is a structural thing rather than a mixing one. +# bin/singdub.py warps another take onto the chart halo3 built FROM f-, and +# that chart is two different kinds of number tangled together: +# +# THE COMPOSITION beats, and `durs` — how many BEATS each unit gets. +# This is the music. It is the same for every take. +# F-'S PERFORMANCE `times` (13 hand-pinned onsets), `sylls` (5 measured +# syllable cuts), `end`. All SECONDS into +# f-whole-line.wav. These describe one singer on one +# day, and nothing about them transfers. +# +# singdub also never reads `lead`/`ants`, so every word it places starts AT +# the slot edge — where halo3 puts the VOWEL on the beat and runs the +# consonant 1:1 before it, the way a singer leans in. A borrowed envelope +# and no runway is exactly "wonky". +# +# So this restarts the process. It keeps the composition and re-measures +# everything else against the take's own audio, which is cheap because +# samples/corpus is already cut per word: the 18 onsets that took a session +# to pin by hand for f- are simply the file boundaries here. Only the +# syllable cuts inside the five multi-syllable words have to be found, and +# they are found in THAT take's voice. +# +# The output is a sidecar halo3 reads, so each take then goes through the +# WHOLE pipeline — consonant runway, boundary snap, energy trim, note +# re-measurement, the weighted warp clock, THE HOLD, nervox, the sibilant +# restore — rather than a warp bolted on afterwards. +# +# pop/.venv/bin/python pop/loner/bin/takechart.py rq sh lg +# PHRASES=w-rq LEAD_ONLY=1 pop/.venv/bin/python pop/loner/bin/halo3.py +import json, os, sys +import numpy as np +import soundfile as sf +import pyworld as pw + +HERE = os.path.dirname(os.path.abspath(__file__)) +LANE = os.path.dirname(HERE) +FRAME_MS = 5.0 +FRAME_S = FRAME_MS / 1000.0 +TONIC = 237.0 +# THE ASSEMBLER HAS TO LEAVE ROOM FOR THE RUNWAY. halo3 puts a word's +# VOWEL on its beat and runs the consonant 1:1 before it, so a word needs +# space to lean back into. The measured runways here reach 0.53 beats +# (0.26 s), and butting the corpus files together at 0.10 s meant a +# consonant either did not fit or ate the end of the word before it. +# The head pad is the same thing for word 0: with "sitting" starting at +# sample 0 there was nowhere for its /s/ to go and the phrase came out +# with leadIn 0.000 — the opening sibilant missing, exactly as it went +# missing from the record. +GAP_S = 0.25 +HEAD_S = 0.40 +# EVERY CUT EDGE IS A CLICK. The corpus files were sliced out of longer +# takes, so each one starts and ends on whatever sample the cut landed on +# — butting eighteen of them together left 754 step discontinuities in +# rq-line against 386 in her own unbroken take, and @jeffrey heard the +# difference: "it sounds so glitchy". A 6 ms cosine at each edge costs +# nothing audible and removes all of them. +EDGE_S = 0.006 +NAMES = "C C# D D# E F F# G G# A A# B".split() + +LYRIC = ("sitting curled up in myself i think of a stone just waiting " + "very patiently for time to pass").split() +# how many syllables each word is sung across — the only thing about the +# split that is compositional. WHERE the cut falls is per-take and measured. +SYLLS = {0: ["sitting·a", "sitting·b"], 4: ["my", "self"], + 11: ["wait", "ing"], 12: ["ve", "ry"], 13: ["pa", "tient", "ly"]} + + +def note_name(hz): + if not hz: + return "?" + m = int(round(69 + 12 * np.log2(hz / 440.0))) + return f"{NAMES[m % 12]}{m // 12 - 1}" + + +def take_words(take): + d = os.path.join(LANE, "samples", "corpus") + idx = {} + for f in os.listdir(d): + if f.endswith(".wav") and f.count("-") >= 2: + tk, _, w = f[:-4].split("-", 2) + if tk == take: + idx[w] = os.path.join(d, f) + return idx if all(w in idx for w in LYRIC) else None + + +def syllable_cuts(x, fs, f0, s, e, k): + """The k−1 seams inside one sung word, found in this take's own voice. + + A syllable boundary is where the voice thins: an unvoiced frame (the + /t/ of pa|tient|ly), or failing that the deepest dip in energy. Score + every interior frame for both, then take the best k−1 that are far + enough apart to be real syllables rather than one wobble counted twice. + """ + f_a, f_b = int(s / FRAME_S), int(e / FRAME_S) + f_b = min(f_b, len(f0)) + if k < 2 or f_b - f_a < 8: + return [] + hop = int(FRAME_S * fs) + rms = np.array([np.sqrt(np.mean(x[i * hop:(i + 1) * hop] ** 2)) + 1e-9 + for i in range(f_a, f_b)]) + db = 20 * np.log10(rms / rms.max()) + voiced = f0[f_a:f_b] > 0 + # skip the word's own onset consonant — that is an edge, not a seam + lo = int(np.argmax(voiced)) if voiced.any() else 0 + lo = max(lo + 2, int(0.12 * len(db))) + hi = len(db) - max(2, int(0.12 * len(db))) + if hi - lo < k: + return [] + score = (~voiced).astype(float) * 6.0 - db / 6.0 + sep = max(2, (hi - lo) // (k + 1)) + picked = [] + order = sorted(range(lo, hi), key=lambda i: -score[i]) + for i in order: + if len(picked) == k - 1: + break + if all(abs(i - j) >= sep for j in picked): + picked.append(i) + return [round(s + i * FRAME_S, 4) for i in sorted(picked)] + + +def build(take, durs, melody, beats): + idx = take_words(take) + if not idx: + print(f" {take}: does not own all 18 lyric words") + return None + y0, fs = sf.read(idx[LYRIC[0]], dtype="float64") + parts, spans, n = [np.zeros(int(HEAD_S * fs))], [], int(HEAD_S * fs) + for w in LYRIC: + y, fs = sf.read(idx[w], dtype="float64") + if y.ndim > 1: + y = y.mean(axis=1) + e = min(int(EDGE_S * fs), len(y) // 4) + if e > 1: + ramp = 0.5 - 0.5 * np.cos(np.linspace(0.0, np.pi, e)) + y = y.copy() + y[:e] *= ramp + y[-e:] *= ramp[::-1] + spans.append((n / fs, (n + len(y)) / fs)) + parts.append(y) + n += len(y) + g = np.zeros(int(GAP_S * fs)) + parts.append(g) + n += len(g) + x = np.concatenate(parts[:-1]) # no trailing breath + slice_name = f"{take}-line" + sf.write(os.path.join(LANE, "samples", f"{slice_name}.wav"), x, fs) + + f0r, t = pw.harvest(x, fs, f0_floor=80.0, f0_ceil=600.0, frame_period=FRAME_MS) + f0 = pw.stonemask(x, f0r, t, fs) + + words = [] + for i, (w, (s, e)) in enumerate(zip(LYRIC, spans)): + seg = f0[int(s / FRAME_S):int(e / FRAME_S)] + seg = seg[seg > 0] + hz = float(np.median(seg)) if len(seg) else 0.0 + words.append(dict(t=w, start=round(s, 4), end=round(e, 4), + f0_hz=round(hz, 1), note=note_name(hz))) + + sylls = {} + for wi, labels in SYLLS.items(): + s, e = spans[wi] + cuts = syllable_cuts(x, fs, f0, s, e, len(labels)) + if len(cuts) != len(labels) - 1: + print(f" {take}: could not seam {LYRIC[wi]} — left whole") + continue + sylls[str(wi)] = [[None, labels[0]]] + [[c, labels[j + 1]] + for j, c in enumerate(cuts)] + + med = float(np.median(f0[f0 > 0])) if (f0 > 0).any() else 0.0 + return dict( + slice=dict(source=f"corpus/{take}", start=0.0, end=round(len(x) / fs, 3), + words="the whole lyric, assembled from corpus", + dur=round(len(x) / fs, 3), median_f0_hz=round(med, 1), + word_f0=words), + align=dict(model="corpus", text=" ".join(LYRIC), words=words), + chart=dict(slice=slice_name, beats=beats, lead=0.0, + durs={str(i): d for i, d in enumerate(durs)}, + # THE MELODY IS THE SONG, not the singer. The first cut + # of this file kept only `durs` as compositional and let + # each take's notes be re-measured from its own voice — + # @jeffrey: "whoa the pitches are way off now". They + # were: every take was being autotuned to the nearest + # scale degree of ITS OWN contour, so it sang its own + # tune in its own octave. Rhythm AND melody are the + # composition; only the TIMING — onsets, syllable + # seams, consonant runways — belongs to the take. + melody=melody, + sylls=sylls, + times={str(i): round(s, 4) for i, (s, _) in enumerate(spans)}, + end=round(spans[-1][1], 4)), + name=slice_name) + + +def main(): + takes = sys.argv[1:] + if not takes: + print("usage: takechart.py [take…]"); return + # THE COMPOSITION, read off the built chart rather than restated: unit + # lengths in BEATS, which is the one part of w-whole-line that is the + # song and not the singer. + built = json.load(open(os.path.join(LANE, "vox4", ".chart.json")))["w-whole-line"] + durs = [n["dur"] for n in built["notes"]] + melody = [n["st"] for n in built["notes"]] + beats = round(sum(durs), 4) + print(f"→ the composition: {len(durs)} units, {beats} beats, " + f"melody {min(melody)}..{max(melody)} st") + + path = os.path.join(LANE, "samples", ".takecharts.json") + out = json.load(open(path)) if os.path.exists(path) else {} + for tk in takes: + r = build(tk, durs, melody, beats) + if not r: + continue + out[f"w-{tk}"] = r + cuts = sum(len(v) - 1 for v in r["chart"]["sylls"].values()) + print(f" ✓ w-{tk:4s} → samples/{r['name']}.wav " + f"{r['slice']['dur']:5.2f}s · 18 words pinned exactly · " + f"{cuts} syllable seams found · median {r['slice']['median_f0_hz']:.0f} Hz") + json.dump(out, open(path, "w"), indent=1) + print(f"WROTE {path} ({len(out)} takes)") + + +main() diff --git a/pop/loner/bin/takes.py b/pop/loner/bin/takes.py new file mode 100644 --- /dev/null +++ b/pop/loner/bin/takes.py @@ -0,0 +1,99 @@ +# takes.py — every utterance she has, across every take. +# +# @jeffrey: "process other takes of the whistlegraph / other lyrics / +# samples · that we can use for harmonizes and other lines / swap out +# utterances as needed or whjatnot". +# +# Swapping a word today means remembering which take had a better "pa" +# and hunting for it. This makes it a lookup: every aligned slice's words, +# each with the span that holds it, the pitch she actually sings there, +# and how far that sits off the A# minor grid in her own 237 Hz frame. +# Words are keyed by their lowercased text, so `stone` lists every stone +# in the bank side by side and a swap is a choice between measured +# options rather than a memory. +# +# Same measurements as audit.py — one instrument for the whole lane. +# +# pop/.venv/bin/python pop/loner/bin/takes.py # the index +# pop/.venv/bin/python pop/loner/bin/takes.py stone # one word + +import json, os, sys +import numpy as np +import soundfile as sf + +HERE = os.path.dirname(os.path.abspath(__file__)) +LANE = os.path.dirname(HERE) +sys.path.insert(0, HERE) +from audit import columns, TONIC, FRAME_S + +MINOR = [0, 2, 3, 5, 7, 8, 10] +NAMES = ["A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A"] + + +def note_name(st): + """Her semitone, as a name in the take's own frame (A#3 = 0).""" + k = int(round(st)) + return f"{NAMES[k % 12]}{3 + (k + 0) // 12}" + + +def off_grid(st): + """Cents from the nearest scale tone — how far she is from the grid.""" + pc = (st * 100.0) % 1200.0 + return min(((pc - g * 100.0 + 600) % 1200) - 600 for g in MINOR + [12]) + + +def main(): + want = sys.argv[1].lower() if len(sys.argv) > 1 else None + align = json.load(open(os.path.join(LANE, "samples", ".align.json"))) + man = json.load(open(os.path.join(LANE, "samples", ".manifest.json"))) + index = {} + + for slice_name in sorted(align): + wav = os.path.join(LANE, "samples", f"{slice_name}.wav") + if not os.path.exists(wav): + continue + x, fs = sf.read(wav, dtype="float64") + if x.ndim > 1: + x = x.mean(axis=1) + f0, st, rms, hi, peak, m = columns(x, fs) + + for w in align[slice_name]["words"]: + a, b = w["start"], w["end"] + k0, k1 = int(a / FRAME_S), min(m, int(b / FRAME_S)) + seg = st[k0:max(k0 + 1, k1)] + seg = seg[~np.isnan(seg)] + if not len(seg): + continue + med = float(np.median(seg)) + db = 20.0 * np.log10(max(float(np.max(rms[k0:max(k0 + 1, k1)])), 1e-9) / peak) + index.setdefault(w["t"].lower().strip(".,!?"), []).append(dict( + slice=slice_name, take=slice_name.split("-")[0], + start=round(a, 3), end=round(b, 3), dur=round(b - a, 3), + st=round(med, 2), note=note_name(med), + cents=round(off_grid(med)), peak_db=round(db, 1))) + + path = os.path.join(LANE, "samples", ".takes.json") + json.dump(index, open(path, "w"), indent=1, sort_keys=True) + + words = [want] if want else sorted(index) + multi = sum(1 for k in index if len({e["take"] for e in index[k]}) > 1) + if not want: + print(f"{len(index)} distinct utterances across " + f"{len({e['slice'] for v in index.values() for e in v})} takes · " + f"{multi} exist in more than one take\n") + for k in words: + if k not in index: + print(f" {k}: not in the bank") + continue + rows = sorted(index[k], key=lambda e: (e["take"], e["slice"])) + print(f" {k}") + for e in rows: + print(f" {e['take']} {e['slice']:<22} {e['start']:6.2f}–{e['end']:6.2f}s " + f"({e['dur']:.2f}s) {e['note']:>4} {e['st']:+6.2f}st " + f"{e['cents']:+4d}¢ peak {e['peak_db']:.0f}dB") + if not want: + print(f"\nWROTE {path}") + + +if __name__ == "__main__": + main() diff --git a/pop/loner/bin/timeline.py b/pop/loner/bin/timeline.py --- a/pop/loner/bin/timeline.py +++ b/pop/loner/bin/timeline.py @@ -89,7 +89,12 @@ LYRIC_OFF = (238, 234, 230, 110) BEAT_TINT = [(255, 92, 162, 34), (132, 158, 236, 14), (238, 234, 230, 10), (132, 158, 236, 14)] -chart = json.load(open(os.path.join(LANE, "vox4", ".chart.json")))["w-whole-line"] +# WHICH TAKE IS BEING SCRUTINISED. Every take has its own chart now, with +# its own boundaries and its own consonant runways, so drawing f-'s blocks +# over another take's audio would be a picture of the wrong performance. +PHRASE = os.environ.get("TAKE") or "w-whole-line" +LEADWAV = os.environ.get("TAKE_WAV") or PHRASE +chart = json.load(open(os.path.join(LANE, "vox4", ".chart.json")))[PHRASE] LINE_BEATS = chart["beats"] LINE_BARS = math.ceil(LINE_BEATS / 4.0) PASSES = [0.0] # ONE pass, and no count-in: @@ -122,7 +127,7 @@ # @jeffrey: "check the length of the actual waveforms in the utterances, # not just ur trim etc — map / render those waveforms directly into the # clips". The lead render (vox4/w-whole-line.wav) IS what the study # plays; chart beat b lives at leadIn + b·SPB seconds in that file. -with wave.open(os.path.join(LANE, "vox4", "w-whole-line.wav"), "rb") as wf: +with wave.open(os.path.join(LANE, "vox4", f"{LEADWAV}.wav"), "rb") as wf: VFS = wf.getframerate() VOX = np.frombuffer(wf.readframes(wf.getnframes()), dtype=np.int16).astype(np.float64) / 32768.0 diff --git a/pop/loner/bin/tryout-takes.sh b/pop/loner/bin/tryout-takes.sh new file mode 100644 --- /dev/null +++ b/pop/loner/bin/tryout-takes.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# tryout-takes.sh — hear another take of the line, solo, on ITS OWN chart. +# +# @jeffrey: "our envelopes etc are still fitting like the original samples · +# we need to like restart the whole process for each actual take · or it +# will sound wonky". +# +# It did, and it was. The first version of this script warped a take onto +# the chart halo3 built from f- — f-'s hand-pinned onsets, f-'s syllable +# seams, f-'s consonant runways — so every take arrived wearing one +# singer's phrasing. This restarts the process instead: +# +# 1. takechart.py assemble the line from that take's per-word corpus +# files, pin all 18 onsets exactly, find the syllable +# seams in ITS voice, keep only `durs` from the score +# 2. halo3.py the FULL pipeline on that chart — consonant runway, +# boundary snap, energy trim, note re-measurement, the +# weighted warp clock, THE HOLD, nervox, the sibilant +# restore +# 3. stage one static dB to the f- spine's loudness, so takes are +# compared on performance and not on mic distance +# 4. the study kick + that vocal, and the scrolling piano roll drawn +# from that take's chart rather than from f-'s +# +# Any of the ten takes owning all eighteen lyric words: s pf cp f rq lg sh +# rd hk o — though hk is f- sliced a second time, not a second take. +# +# bash pop/loner/bin/tryout-takes.sh rq sh lg +# → out/takes/-timeline.mp4 (+ .mp3), and on the Desktop +set -euo pipefail +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +LANE="$(dirname "$HERE")" +REPO="$(dirname "$(dirname "$LANE")")" +PY="$REPO/pop/.venv/bin/python" +OUT="$LANE/out/takes" +mkdir -p "$OUT" +cd "$REPO" + +[ $# -gt 0 ] || { echo "usage: tryout-takes.sh [take…]" >&2; exit 1; } + +bash "$LANE/c/build.sh" >/dev/null +"$PY" "$HERE/takechart.py" "$@" 2>/dev/null | grep -E "✓|composition|could not|does not" + +# ONE BAD TAKE MUST NOT END THE BENCH. `set -e` plus a bench loop meant a +# single failure — a take halo3 could not build, a wav timeline.py could +# not open — threw away every take queued behind it. +fail=0 +for t in "$@"; do + echo "── $t ────────────────────────────────────────────" + ( set -e + TAKES=1 PHRASES="w-$t" LEAD_ONLY=1 "$PY" "$HERE/halo3.py" 2>/dev/null \ + | grep -E "^ w-$t" || { echo " ! halo3 built nothing for w-$t"; continue; } + bash "$HERE/stage-takes.sh" "$LANE/vox4/w-$t.wav" "try-$t" + TAKE="w-$t" TAKE_WAV="try-$t" MINIMAL=1 "$LANE/c/lonerremix" | tail -1 + TAKE="w-$t" TAKE_WAV="try-$t" python3 "$HERE/timeline.py" | tail -1 + ffmpeg -y -v error -i "$LANE/out/loner-kickvox-full.wav" \ + -codec:a libmp3lame -q:a 0 "$OUT/$t.mp3" + mv "$LANE/out/loner-kickvox-timeline.mp4" "$OUT/$t-timeline.mp4" + cp "$OUT/$t-timeline.mp4" ~/Desktop/ 2>/dev/null || true + echo " ✓ $OUT/$t-timeline.mp4" ) || { echo " ! $t failed — moving on"; fail=$((fail+1)); } +done +[ "$fail" -eq 0 ] || echo "→ $fail take(s) failed; the rest are in $OUT" diff --git a/pop/loner/bin/tryout.py b/pop/loner/bin/tryout.py new file mode 100644 --- /dev/null +++ b/pop/loner/bin/tryout.py @@ -0,0 +1,107 @@ +# tryout.py — audition every version of a word she actually sang. +# +# @jeffrey: "can we try using other takes for the lead too / go back to +# vocal tests with that? · especially i wanna try out new iterations of +# 'patiently'". +# +# bin/takes.py says WHICH takes hold a word and at what pitch; this one +# renders them, so the choice is made by ear instead of from a table. Each +# candidate goes through the same WORLD chain the chart uses — snap to the +# A# minor grid in her own 237 Hz frame, nervox tremor on the held frames — +# and they are laid out one after another with a gap, loudest-first, so a +# swap can be auditioned before it is charted. +# +# Every variant here is HER, from a take she sang. Generating syllables she +# never sang (an ElevenLabs IVC of Camille, the way the Prutti dub kept +# Prutti's voice) is a different thing and wants her sign-off first — the +# klokkentales gate: label synthetic voice, collab-invite is the consent. +# +# pop/.venv/bin/python pop/loner/bin/tryout.py patiently +# → out/tryout-patiently.wav + a printed legend + +import json, os, sys +import numpy as np +import soundfile as sf +import pyworld as pw + +HERE = os.path.dirname(os.path.abspath(__file__)) +LANE = os.path.dirname(HERE) +sys.path.insert(0, HERE) +sys.path.insert(0, os.path.join(os.path.dirname(LANE), "lib")) +from audit import columns, TONIC, FRAME_S +from nervox import waver as nervox_waver, flange as nervox_flange + +MINOR = np.array([0, 2, 3, 5, 7, 8, 10]) +SNAP = 0.92 +GAP_S = 0.45 + + +def cents_to_grid(hz): + cents = 1200.0 * np.log2(hz / TONIC) + pc = np.mod(cents, 1200.0) + grid = np.concatenate([MINOR * 100.0, [1200.0]]) + dev = pc[:, None] - grid[None, :] + return dev[np.arange(len(pc)), np.argmin(np.abs(dev), axis=1)] + + +def render(x, fs, snap=SNAP, nervy=True): + """The chart's chain, on one word.""" + f0r, t = pw.harvest(x, fs, f0_floor=140.0, f0_ceil=600.0, frame_period=5.0) + f0 = pw.stonemask(x, f0r, t, fs) + fft = pw.get_cheaptrick_fft_size(fs, f0_floor=140.0) + sp = pw.cheaptrick(x, f0, t, fs, fft_size=fft, f0_floor=140.0) + ap = pw.d4c(x, f0, t, fs, fft_size=fft) + v = f0 > 0 + corr = np.zeros_like(f0) + if v.any(): + corr[v] = -cents_to_grid(f0[v]) * snap + f0c = np.where(v, f0 * 2.0 ** (corr / 1200.0), 0.0) + if nervy: + f0c = nervox_waver(f0c, 0.005, voiced=v) + y = pw.synthesize(f0c, sp, ap, fs, frame_period=5.0) + return nervox_flange(y, fs) if nervy else y + + +def main(): + word = (sys.argv[1] if len(sys.argv) > 1 else "patiently").lower() + idx_path = os.path.join(LANE, "samples", ".takes.json") + if not os.path.exists(idx_path): + print("run bin/takes.py first"); return + index = json.load(open(idx_path)) + if word not in index: + print(f"'{word}' is not in the bank — bin/takes.py lists what is"); return + + out, legend, sr = [], [], None + for e in sorted(index[word], key=lambda e: (e["take"], e["slice"])): + wav = os.path.join(LANE, "samples", f"{e['slice']}.wav") + x, fs = sf.read(wav, dtype="float64") + if x.ndim > 1: + x = x.mean(axis=1) + sr = fs + seg = x[int(e["start"] * fs):int(e["end"] * fs)] + if len(seg) < int(0.05 * fs): + continue + for nervy in (False, True): + y = render(seg, fs, nervy=nervy) + pk = np.max(np.abs(y)) or 1.0 + out.append(y / pk * 0.72) + out.append(np.zeros(int(GAP_S * fs))) + legend.append(f"{e['take']}-take {e['slice']:<20} {e['note']:>4} " + f"{e['st']:+5.2f}st {e['dur']:.2f}s " + f"{'nervox' if nervy else 'plain '}") + + if not out: + print("nothing renderable"); return + y = np.concatenate(out) + dest = os.path.join(LANE, "out", f"tryout-{word}.wav") + sf.write(dest, y, sr) + print(f"'{word}' — {len(legend)} variants, in order:\n") + at = 0.0 + for i, l in enumerate(legend): + print(f" {at:5.1f}s {i + 1}. {l}") + at += len(out[i * 2]) / sr + GAP_S + print(f"\nWROTE {dest} ({len(y) / sr:.1f}s)") + + +if __name__ == "__main__": + main() diff --git a/pop/loner/bin/wizard.py b/pop/loner/bin/wizard.py new file mode 100644 --- /dev/null +++ b/pop/loner/bin/wizard.py @@ -0,0 +1,85 @@ +# wizard.py — hand the chart to ChartWizard. +# +# @jeffrey: "can we maybe work on a drag and drop gui for this · so i can +# better adjust timing in realtime for these · like melodyne style · then +# we can recompute and play it back?" +# +# Everything the GUI draws has already been measured somewhere in this +# lane — the warped spans in vox4/.manifest.json, the beat slots and sung +# semitones in vox4/.chart.json, and audit.py's three columns (pitch, +# level, brightness) plus the NOTE/FRIC/PUFF events it splits them into. +# None of that should be re-derived in Swift, where it would drift from +# what halo3 actually renders. So this collects it into one file the app +# opens, and the app writes its edits back to chart-edits.json, which +# halo3 merges over the CHART literal. +# +# pop/.venv/bin/python pop/loner/bin/wizard.py # → vox4/.wizard.json + +import json, os, sys +import numpy as np +import soundfile as sf + +HERE = os.path.dirname(os.path.abspath(__file__)) +LANE = os.path.dirname(HERE) +sys.path.insert(0, HERE) +from audit import columns, events, TONIC, FRAME_S # one set of measurements + +BPM = 122.0 + + +def main(): + chart = json.load(open(os.path.join(LANE, "vox4", ".chart.json"))) + man = json.load(open(os.path.join(LANE, "vox4", ".manifest.json"))) + out = {"lane": os.path.basename(LANE), "bpm": BPM, "tonic": TONIC, + "frame_s": FRAME_S, "phrases": {}} + + for name, ch in chart.items(): + # a phrase only reaches the GUI once halo3 has actually warped it — + # a partial build (PHRASES=…) leaves the others without spans. + if name not in man or "spans" not in man[name]: + continue + slice_name = man[name]["slice"] + wav = os.path.join(LANE, "samples", f"{slice_name}.wav") + if not os.path.exists(wav): + continue + x, fs = sf.read(wav, dtype="float64") + if x.ndim > 1: + x = x.mean(axis=1) + + f0, st, rms, hi, peak, m = columns(x, fs) + db = 20.0 * np.log10(np.maximum(rms, 1e-9) / peak) + spans = {t: (a, b) for (t, a, b) in man[name]["spans"]} + + # a unit is one word block: where it sits on the grid, and which + # piece of her the block plays. The GUI drags exactly these two. + units = [] + for n in ch["notes"]: + a, b = spans.get(n["t"], (0.0, 0.0)) + units.append({"t": n["t"], "beat": n["beat"], "dur": n["dur"], + "st": n["st"], "src0": a, "src1": b}) + + out["phrases"][name] = { + "slice": slice_name, "wav": wav, "sr": int(fs), + "leadIn": ch.get("leadIn", 0.0), "beats": ch["beats"], + "units": units, + "events": [{"a": a, "b": b, "kind": k, + "st": (None if np.isnan(s) else round(float(s), 2))} + for (a, b, s, k) in events(x, fs)], + # the three columns, rounded to what a screen can show + "frames": { + "st": [None if np.isnan(v) else round(float(v), 2) for v in st], + "db": [round(float(v), 1) for v in db], + "hf": [round(float(v), 2) for v in hi], + }, + } + print(f" {name:>20} {len(units)} units · {len(out['phrases'][name]['events'])} events " + f"· {m} frames") + + path = os.path.join(LANE, "vox4", ".wizard.json") + json.dump(out, open(path, "w")) + print(f"WROTE {path} ({os.path.getsize(path) // 1024} KB, " + f"{len(out['phrases'])} phrases)") + + +if __name__ == "__main__": + main() diff --git a/pop/loner/c/cut-club.sh b/pop/loner/c/cut-club.sh new file mode 100644 --- /dev/null +++ b/pop/loner/c/cut-club.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# cut-club.sh — Lonerclub, mastered hot. +# +# @jeffrey: "make a nice hot club mix". cut-v4.sh targets −14 LUFS, which +# is a release level; a club plays loud and wants the record to arrive +# already committed. This targets −9. +# +# It keeps the lane's mastering law — MEASURE → one static dB → true-peak +# limiter, never a second loudnorm — and buys the extra 5 dB the honest +# way rather than by slamming the limiter with it: +# +# 1. a gentle bus COMPRESSOR first, so the limiter is catching peaks +# rather than doing the levelling. 5 dB of limiting with no +# compression is where a master starts to flap. +# 2. a shelf pair, not a smile: +1.2 dB under 90 Hz for the floor and a +# NARROW +1 dB at 2.8 kHz for her consonants. No broad treble lift — +# pop/wattajetta: master treble boosts read as tang on laptop +# speakers, and this cut has bells in the sixth octave now. +# 3. the limiter sits at 0.82, not at the ceiling. mp3 encoding +# invents inter-sample peaks: limiting to −1.0 dBFS measured −0.3 +# dBTP after the encode. Leaving 1.7 dB of headroom in the wav is +# what actually lands the MP3 under −1. Louder than that is not +# loudness, it is distortion on someone's phone. +set -euo pipefail + +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +LANE="$(dirname "$HERE")" +OUT="$LANE/out" + +FULL="${1:-$OUT/loner-remix-v4-full.wav}" +DEST="${2:-$OUT/lonerclub.mp3}" +TARGET="${TARGET:--9.0}" + +echo "→ measure $(basename "$FULL")" +STATS=$(ffmpeg -hide_banner -nostats -i "$FULL" \ + -af loudnorm=I="$TARGET":TP=-1.0:LRA=9:print_format=json -f null - 2>&1 | awk '/^\{/,/^\}/') +MI=$(echo "$STATS" | grep '"input_i"' | head -1 | sed 's/.*: *"\([^"]*\)".*/\1/') +# leave room for the compressor to find; the static move is the rest. +# 2.2 dB was right when the bus glue was the ONLY levelling in the chain. +# The vox bus now carries its own compressor (lonerremix.c, "THE VOCAL +# CHAIN"), so asking this one for the same work again squashed LRA to 1.9 +# — a flat master. It only has to catch peaks now. +GAIN=$(awk -v i="$MI" -v t="$TARGET" 'BEGIN{printf "%.2f", t-i-1.1}') +echo " measured I=$MI → static ${GAIN} dB, then glue, then limit" + +ffmpeg -y -v error -i "$FULL" -af "\ +volume=${GAIN}dB,\ +acompressor=threshold=0.22:ratio=1.5:attack=30:release=240:makeup=1.1:knee=6,\ +equalizer=f=90:t=q:w=0.9:g=1.2,\ +equalizer=f=2800:t=q:w=1.6:g=1.0,\ +alimiter=limit=0.82:attack=4:release=90:level=disabled" \ + -ar 48000 -c:a pcm_s24le "$OUT/lonerclub-master.wav" + +ffmpeg -y -v error -i "$OUT/lonerclub-master.wav" -c:a libmp3lame -b:a 320k \ + -metadata title="Lonerclub" \ + -metadata artist="Whistlegraph" -metadata album="pop / loner" \ + -metadata comment="Camille Klein's whistlegraph 'loner', regulated onto a strict 122 floor: one sung sentence looped five times, harmony accumulating. WORLD snap 0.92 with nervox tremor, per-word beat chart, FEM bells, her own backup 3rds and 5ths." \ + "$DEST" + +ffmpeg -hide_banner -nostats -i "$DEST" -af ebur128=peak=true -f null - 2>&1 \ + | grep -E "^\s+(I|LRA|Peak):" +echo "✓ $DEST" diff --git a/pop/loner/c/loner-chart.h b/pop/loner/c/loner-chart.h --- a/pop/loner/c/loner-chart.h +++ b/pop/loner/c/loner-chart.h @@ -8,100 +8,318 @@ #define CHART_BPM 122.0 #define CHART_TONIC 237.0 -typedef struct { double beat, dur; int st; } ChartNote; +// `t` is the unit's label — the C addresses a word by name so a +// treatment can be written against "pa" rather than against unit 17. +typedef struct { double beat, dur; int st; const char *t; } ChartNote; typedef struct { const char *name; double leadIn; double beats; int n; const ChartNote *notes; } ChartPhrase; static const ChartNote w_whole_line_notes[] = { - { 0.00, 2.00, 7 }, - { 2.00, 2.00, 5 }, - { 4.00, 1.91, 3 }, - { 5.91, 2.09, 2 }, - { 8.00, 1.50, 0 }, - { 9.50, 1.50, 5 }, - { 11.00, 2.00, 2 }, - { 13.00, 2.00, -2 }, - { 15.00, 2.00, -5 }, - { 17.00, 4.00, 12 }, - { 21.00, 3.00, 10 }, - { 24.00, 3.00, 5 }, - { 27.00, 4.00, 2 }, - { 31.00, 2.00, 3 }, - { 33.00, 2.00, 2 }, - { 35.00, 2.00, 0 }, - { 37.00, 2.00, -2 }, - { 39.00, 2.00, 7 }, - { 41.00, 2.50, 5 }, - { 43.50, 2.50, 3 }, - { 46.00, 2.00, 5 }, - { 48.00, 4.00, 7 }, - { 52.00, 4.00, 3 }, - { 56.00, 3.00, 3 }, + { 0.00, 2.00, 7, "sitting·a" }, + { 2.00, 2.00, 5, "sitting·b" }, + { 4.00, 1.91, 3, "curled" }, + { 5.91, 2.09, 2, "up" }, + { 8.00, 2.00, 0, "in" }, + { 10.00, 1.50, 5, "my" }, + { 11.50, 2.50, 2, "self" }, + { 14.00, 2.00, -2, "i" }, + { 16.00, 2.00, -5, "think" }, + { 18.00, 4.00, 12, "of" }, + { 22.00, 1.75, 10, "a" }, + { 23.75, 4.25, 5, "stone" }, + { 28.00, 4.00, 2, "just" }, + { 32.00, 2.00, 3, "wait" }, + { 34.00, 2.00, 2, "ing" }, + { 36.00, 2.00, 0, "ve" }, + { 38.00, 2.00, -2, "ry" }, + { 40.00, 2.00, 7, "pa" }, + { 42.00, 2.00, 5, "tient" }, + { 44.00, 2.00, 3, "ly" }, + { 46.00, 2.00, 5, "for" }, + { 48.00, 4.00, 7, "time" }, + { 52.00, 4.00, 3, "to" }, + { 56.00, 4.00, 3, "pass" }, }; static const ChartNote w_sitting_curled_notes[] = { - { 0.00, 3.00, 6 }, - { 3.00, 2.00, 3 }, - { 5.00, 1.50, 2 }, - { 6.50, 1.50, 0 }, - { 8.00, 3.00, 5 }, + { 0.00, 3.00, 6, "Sitting" }, + { 3.00, 2.00, 3, "curled" }, + { 5.00, 1.50, 2, "up" }, + { 6.50, 1.50, 0, "in" }, + { 8.00, 3.00, 5, "myself" }, }; static const ChartNote w_i_think_notes[] = { - { 0.00, 2.00, -2 }, - { 2.00, 1.50, -5 }, + { 0.00, 2.00, -2, "I" }, + { 2.00, 1.50, -5, "think" }, }; static const ChartNote w_of_a_stone_notes[] = { - { 0.00, 4.00, 12 }, - { 4.00, 2.00, 10 }, - { 6.00, 2.00, 5 }, + { 0.00, 4.00, 12, "of" }, + { 4.00, 2.00, 10, "a" }, + { 6.00, 2.00, 5, "stone" }, }; static const ChartNote w_just_waiting_notes[] = { - { 0.00, 3.50, 2 }, - { 3.50, 3.00, 3 }, + { 0.00, 3.50, 2, "Just" }, + { 3.50, 3.00, 3, "waiting" }, }; static const ChartNote w_very_patiently_notes[] = { - { 0.00, 5.00, 0 }, - { 5.00, 3.50, 7 }, + { 0.00, 5.00, 0, "very" }, + { 5.00, 3.50, 7, "patiently" }, }; static const ChartNote w_for_time_to_pass_notes[] = { - { 0.00, 2.00, 5 }, - { 2.00, 2.50, 7 }, - { 4.50, 4.00, 3 }, - { 8.50, 4.00, 3 }, + { 0.00, 2.00, 5, "for" }, + { 2.00, 2.50, 7, "time" }, + { 4.50, 4.00, 3, "to" }, + { 8.50, 4.00, 3, "pass" }, }; static const ChartNote w_n_getting_curled_notes[] = { - { 0.00, 1.50, 5 }, - { 1.50, 2.50, 3 }, - { 4.00, 0.50, 1 }, - { 4.50, 1.50, 0 }, - { 6.00, 2.50, 4 }, - { 8.50, 2.00, -2 }, - { 10.50, 0.50, -5 }, + { 0.00, 1.50, 5, "getting" }, + { 1.50, 2.50, 3, "curled" }, + { 4.00, 0.50, 1, "up" }, + { 4.50, 1.50, 0, "in" }, + { 6.00, 2.50, 4, "myself" }, + { 8.50, 2.00, -2, "i" }, + { 10.50, 0.50, -5, "think" }, }; static const ChartNote w_n_stone_waiting_notes[] = { - { 0.00, 2.00, 12 }, - { 2.00, 2.00, 9 }, - { 4.00, 4.00, 5 }, - { 8.00, 4.00, 3 }, - { 12.00, 3.00, 0 }, - { 15.00, 2.00, 6 }, + { 0.00, 2.00, 12, "A" }, + { 2.00, 2.00, 9, "stone" }, + { 4.00, 4.00, 5, "just" }, + { 8.00, 4.00, 3, "waiting" }, + { 12.00, 3.00, 0, "very" }, + { 15.00, 2.00, 6, "patiently" }, }; static const ChartNote w_n_for_time_to_pass_notes[] = { - { 0.00, 0.50, 5 }, - { 0.50, 1.00, 7 }, - { 1.50, 2.50, 3 }, - { 4.00, 1.50, 3 }, + { 0.00, 0.50, 5, "the" }, + { 0.50, 1.00, 7, "time" }, + { 1.50, 2.50, 3, "to" }, + { 4.00, 1.50, 3, "pass" }, +}; +static const ChartNote w_rq_notes[] = { + { 0.00, 2.00, -5, "sitting·a" }, + { 2.00, 2.00, -7, "sitting·b" }, + { 4.00, 1.91, -9, "curled" }, + { 5.91, 2.09, -10, "up" }, + { 8.00, 2.00, -12, "in" }, + { 10.00, 1.50, -7, "my" }, + { 11.50, 2.50, -10, "self" }, + { 14.00, 2.00, -14, "i" }, + { 16.00, 2.00, -17, "think" }, + { 18.00, 4.00, 0, "of" }, + { 22.00, 1.75, -2, "a" }, + { 23.75, 4.25, -7, "stone" }, + { 28.00, 4.00, -10, "just" }, + { 32.00, 2.00, -9, "wait" }, + { 34.00, 2.00, -10, "ing" }, + { 36.00, 2.00, -12, "ve" }, + { 38.00, 2.00, -14, "ry" }, + { 40.00, 2.00, -5, "pa" }, + { 42.00, 2.00, -7, "tient" }, + { 44.00, 2.00, -9, "ly" }, + { 46.00, 2.00, -7, "for" }, + { 48.00, 4.00, -5, "time" }, + { 52.00, 4.00, -9, "to" }, + { 56.00, 4.00, -9, "pass" }, +}; +static const ChartNote w_sh_notes[] = { + { 0.00, 2.00, -5, "sitting·a" }, + { 2.00, 2.00, -7, "sitting·b" }, + { 4.00, 1.91, -9, "curled" }, + { 5.91, 2.09, -10, "up" }, + { 8.00, 2.00, -12, "in" }, + { 10.00, 1.50, -7, "my" }, + { 11.50, 2.50, -10, "self" }, + { 14.00, 2.00, -14, "i" }, + { 16.00, 2.00, -17, "think" }, + { 18.00, 4.00, 0, "of" }, + { 22.00, 1.75, -2, "a" }, + { 23.75, 4.25, -7, "stone" }, + { 28.00, 4.00, -10, "just" }, + { 32.00, 2.00, -9, "wait" }, + { 34.00, 2.00, -10, "ing" }, + { 36.00, 2.00, -12, "ve" }, + { 38.00, 2.00, -14, "ry" }, + { 40.00, 2.00, -5, "pa" }, + { 42.00, 2.00, -7, "tient" }, + { 44.00, 2.00, -9, "ly" }, + { 46.00, 2.00, -7, "for" }, + { 48.00, 4.00, -5, "time" }, + { 52.00, 4.00, -9, "to" }, + { 56.00, 4.00, -9, "pass" }, +}; +static const ChartNote w_lg_notes[] = { + { 0.00, 2.00, 7, "sitting·a" }, + { 2.00, 2.00, 5, "sitting·b" }, + { 4.00, 1.91, 3, "curled" }, + { 5.91, 2.09, 2, "up" }, + { 8.00, 2.00, 0, "in" }, + { 10.00, 1.50, 5, "my" }, + { 11.50, 2.50, 2, "self" }, + { 14.00, 2.00, -2, "i" }, + { 16.00, 2.00, -5, "think" }, + { 18.00, 4.00, 12, "of" }, + { 22.00, 1.75, 10, "a" }, + { 23.75, 4.25, 5, "stone" }, + { 28.00, 4.00, 2, "just" }, + { 32.00, 2.00, 3, "wait" }, + { 34.00, 2.00, 2, "ing" }, + { 36.00, 2.00, 0, "ve" }, + { 38.00, 2.00, -2, "ry" }, + { 40.00, 2.00, 7, "pa" }, + { 42.00, 2.00, 5, "tient" }, + { 44.00, 2.00, 3, "ly" }, + { 46.00, 2.00, 5, "for" }, + { 48.00, 4.00, 7, "time" }, + { 52.00, 4.00, 3, "to" }, + { 56.00, 4.00, 3, "pass" }, +}; +static const ChartNote w_pf_notes[] = { + { 0.00, 2.00, 7, "sitting·a" }, + { 2.00, 2.00, 5, "sitting·b" }, + { 4.00, 1.91, 3, "curled" }, + { 5.91, 2.09, 2, "up" }, + { 8.00, 2.00, 0, "in" }, + { 10.00, 1.50, 5, "my" }, + { 11.50, 2.50, 2, "self" }, + { 14.00, 2.00, -2, "i" }, + { 16.00, 2.00, -5, "think" }, + { 18.00, 4.00, 12, "of" }, + { 22.00, 1.75, 10, "a" }, + { 23.75, 4.25, 5, "stone" }, + { 28.00, 4.00, 2, "just" }, + { 32.00, 2.00, 3, "wait" }, + { 34.00, 2.00, 2, "ing" }, + { 36.00, 2.00, 0, "ve" }, + { 38.00, 2.00, -2, "ry" }, + { 40.00, 2.00, 7, "pa" }, + { 42.00, 2.00, 5, "tient" }, + { 44.00, 2.00, 3, "ly" }, + { 46.00, 2.00, 5, "for" }, + { 48.00, 4.00, 7, "time" }, + { 52.00, 4.00, 3, "to" }, + { 56.00, 4.00, 3, "pass" }, +}; +static const ChartNote w_rd_notes[] = { + { 0.00, 2.00, 7, "sitting·a" }, + { 2.00, 2.00, 5, "sitting·b" }, + { 4.00, 1.91, 3, "curled" }, + { 5.91, 2.09, 2, "up" }, + { 8.00, 2.00, 0, "in" }, + { 10.00, 1.50, 5, "my" }, + { 11.50, 2.50, 2, "self" }, + { 14.00, 2.00, -2, "i" }, + { 16.00, 2.00, -5, "think" }, + { 18.00, 4.00, 12, "of" }, + { 22.00, 1.75, 10, "a" }, + { 23.75, 4.25, 5, "stone" }, + { 28.00, 4.00, 2, "just" }, + { 32.00, 2.00, 3, "wait" }, + { 34.00, 2.00, 2, "ing" }, + { 36.00, 2.00, 0, "ve" }, + { 38.00, 2.00, -2, "ry" }, + { 40.00, 2.00, 7, "pa" }, + { 42.00, 2.00, 5, "tient" }, + { 44.00, 2.00, 3, "ly" }, + { 46.00, 2.00, 5, "for" }, + { 48.00, 4.00, 7, "time" }, + { 52.00, 4.00, 3, "to" }, + { 56.00, 4.00, 3, "pass" }, +}; +static const ChartNote w_cp_notes[] = { + { 0.00, 2.00, -5, "sitting·a" }, + { 2.00, 2.00, -7, "sitting·b" }, + { 4.00, 1.91, -9, "curled" }, + { 5.91, 2.09, -10, "up" }, + { 8.00, 2.00, -12, "in" }, + { 10.00, 1.50, -7, "my" }, + { 11.50, 2.50, -10, "self" }, + { 14.00, 2.00, -14, "i" }, + { 16.00, 2.00, -17, "think" }, + { 18.00, 4.00, 0, "of" }, + { 22.00, 1.75, -2, "a" }, + { 23.75, 4.25, -7, "stone" }, + { 28.00, 4.00, -10, "just" }, + { 32.00, 2.00, -9, "wait" }, + { 34.00, 2.00, -10, "ing" }, + { 36.00, 2.00, -12, "ve" }, + { 38.00, 2.00, -14, "ry" }, + { 40.00, 2.00, -5, "pa" }, + { 42.00, 2.00, -7, "tient" }, + { 44.00, 2.00, -9, "ly" }, + { 46.00, 2.00, -7, "for" }, + { 48.00, 4.00, -5, "time" }, + { 52.00, 4.00, -9, "to" }, + { 56.00, 4.00, -9, "pass" }, +}; +static const ChartNote w_s_notes[] = { + { 0.00, 2.00, 7, "sitting·a" }, + { 2.00, 2.00, 5, "sitting·b" }, + { 4.00, 1.91, 3, "curled" }, + { 5.91, 2.09, 2, "up" }, + { 8.00, 2.00, 0, "in" }, + { 10.00, 1.50, 5, "my" }, + { 11.50, 2.50, 2, "self" }, + { 14.00, 2.00, -2, "i" }, + { 16.00, 2.00, -5, "think" }, + { 18.00, 4.00, 12, "of" }, + { 22.00, 1.75, 10, "a" }, + { 23.75, 4.25, 5, "stone" }, + { 28.00, 4.00, 2, "just" }, + { 32.00, 2.00, 3, "wait" }, + { 34.00, 2.00, 2, "ing" }, + { 36.00, 2.00, 0, "ve" }, + { 38.00, 2.00, -2, "ry" }, + { 40.00, 2.00, 7, "pa" }, + { 42.00, 2.00, 5, "tient" }, + { 44.00, 2.00, 3, "ly" }, + { 46.00, 2.00, 5, "for" }, + { 48.00, 4.00, 7, "time" }, + { 52.00, 4.00, 3, "to" }, + { 56.00, 4.00, 3, "pass" }, +}; +static const ChartNote w_o_notes[] = { + { 0.00, 2.00, 7, "sitting·a" }, + { 2.00, 2.00, 5, "sitting·b" }, + { 4.00, 1.91, 3, "curled" }, + { 5.91, 2.09, 2, "up" }, + { 8.00, 2.00, 0, "in" }, + { 10.00, 1.50, 5, "my" }, + { 11.50, 2.50, 2, "self" }, + { 14.00, 2.00, -2, "i" }, + { 16.00, 2.00, -5, "think" }, + { 18.00, 4.00, 12, "of" }, + { 22.00, 1.75, 10, "a" }, + { 23.75, 4.25, 5, "stone" }, + { 28.00, 4.00, 2, "just" }, + { 32.00, 2.00, 3, "wait" }, + { 34.00, 2.00, 2, "ing" }, + { 36.00, 2.00, 0, "ve" }, + { 38.00, 2.00, -2, "ry" }, + { 40.00, 2.00, 7, "pa" }, + { 42.00, 2.00, 5, "tient" }, + { 44.00, 2.00, 3, "ly" }, + { 46.00, 2.00, 5, "for" }, + { 48.00, 4.00, 7, "time" }, + { 52.00, 4.00, 3, "to" }, + { 56.00, 4.00, 3, "pass" }, }; static const ChartPhrase CHART[] = { - { "w-whole-line", 0.040, 59.00, 24, w_whole_line_notes }, - { "w-sitting-curled", 0.020, 11.00, 5, w_sitting_curled_notes }, - { "w-i-think", 0.020, 3.50, 2, w_i_think_notes }, + { "w-whole-line", 0.330, 60.00, 24, w_whole_line_notes }, + { "w-sitting-curled", 0.040, 11.00, 5, w_sitting_curled_notes }, + { "w-i-think", 0.040, 3.50, 2, w_i_think_notes }, { "w-of-a-stone", 0.000, 8.00, 3, w_of_a_stone_notes }, - { "w-just-waiting", 0.075, 6.50, 2, w_just_waiting_notes }, + { "w-just-waiting", 0.150, 6.50, 2, w_just_waiting_notes }, { "w-very-patiently", 0.000, 8.50, 2, w_very_patiently_notes }, - { "w-for-time-to-pass", 0.035, 12.50, 4, w_for_time_to_pass_notes }, + { "w-for-time-to-pass", 0.070, 12.50, 4, w_for_time_to_pass_notes }, { "w-n-getting-curled", 0.000, 11.00, 7, w_n_getting_curled_notes }, { "w-n-stone-waiting", 0.000, 17.00, 6, w_n_stone_waiting_notes }, { "w-n-for-time-to-pass", 0.000, 5.50, 4, w_n_for_time_to_pass_notes }, + { "w-rq", 0.430, 60.00, 24, w_rq_notes }, + { "w-sh", 0.840, 60.00, 24, w_sh_notes }, + { "w-lg", 0.575, 60.00, 24, w_lg_notes }, + { "w-pf", 0.765, 60.00, 24, w_pf_notes }, + { "w-rd", 0.405, 60.00, 24, w_rd_notes }, + { "w-cp", 0.430, 60.00, 24, w_cp_notes }, + { "w-s", 0.370, 60.00, 24, w_s_notes }, + { "w-o", 0.550, 60.00, 24, w_o_notes }, }; -#define CHART_N 10 +#define CHART_N 18 diff --git a/pop/loner/c/lonerremix.c b/pop/loner/c/lonerremix.c --- a/pop/loner/c/lonerremix.c +++ b/pop/loner/c/lonerremix.c @@ -65,7 +65,14 @@ #define SR 48000 #define TAU 6.283185307179586 static const double BPM = CHART_BPM; // 122 — the chart's clock static const double TONIC = CHART_TONIC; // 237 Hz — Camille's frame -#define BARS 76 +// @jeffrey: "instrumental intro" → "can the intro be like just 1 bar" → +// "can we start it as sitting from the first beat?". None, in the end, and +// it is the right answer for this song: three minutes of one sentence does +// not need announcing. The first sound on the record is her /s/. +#define INTRO 0 +#define BARS (INTRO + 96) // Lonerclub — six passes after the intro +// the passes, addressed by number rather than by remembering an offset +#define L(n) (INTRO + (n) * 16) #define TAIL_S 6.0 static double BEAT, BAR, STEP; // set in main static long N; @@ -74,7 +81,11 @@ // ── buses ────────────────────────────────────────────────────────────── static float *drumsL, *drumsR, *musicL, *musicR, *voxL, *voxR; static float *sideV, *sideB, *dlySend, *rvbSend; -static const double VOXG = 1.42; +// @jeffrey: "could we have the vocals be deeper in the mix". 1.42 put her +// right at the front of the speaker. Depth is not just a smaller number +// though — a quiet close voice is still a close voice — so the fader comes +// down AND the sends go up AND the chest comes out (see THE VOCAL CHAIN). +static const double VOXG = 0.82; // ── helpers ──────────────────────────────────────────────────────────── static double clampd(double v, double a, double b) { return v < a ? a : v > b ? b : v; } @@ -83,12 +94,55 @@ static double tail_fade(long i, long n) { double u = (double)(n - 1 - i) / (0.010 * SR); return u >= 1 ? 1 : u <= 0 ? 0 : u * u * (3 - 2 * u); } -static double at(double bar) { return bar * BAR; } +// THE CONSONANT RUNWAY NEEDS SOMEWHERE TO LIVE. voice_line places a phrase +// at at(bar) − leadIn, so her VOWEL lands on the beat and the consonant +// runs 1:1 before it, the way a singer leans in. At bar 0 that is NEGATIVE +// TIME, and emit() drops anything before sample 0 — so the 220 ms /s/ that +// opens "sitting" was not buried under the kick, it was never written to +// the file at all. Only the first pass lost it; bars 16, 48 and 80 have +// their runway. @jeffrey, twice: "the opening 's' is not hearable". +// +// @jeffrey: "can we start it as sitting from the first beat?" — with no +// intro at all, which puts the problem straight back: her /s/ has to run +// before the downbeat and there is nothing before the downbeat. +// +// A whole BEAT of pre-roll was the crude fix and it left 492 ms of silence +// at the head of the record. The exact fix is the phrase's own leadIn: +// pre-roll by precisely the runway that phrase needs, so the file opens ON +// the first sample of her /s/, her vowel lands on beat 1, and there is no +// silence anywhere. Nothing is trimmed and nothing is padded. +static double PREROLL = 0.0; +static double at(double bar) { return PREROLL + bar * BAR; } static double hz_of(double st) { return TONIC * pow(2.0, st / 12.0); } static uint32_t seed = 20260817u; static double rnd(void) { seed = seed * 1664525u + 1013904223u; return seed / 4294967296.0; } static double jit(double ms) { return ((rnd() - 0.5) * 2 * ms) / 1000.0; } + +// ── BOP ─────────────────────────────────────────────────────────────── +// @jeffrey: "any way we can add more bop / more jazz and humanization to +// the beat too?" +// +// SWING is the whole of the first half. A straight 16th grid is a machine +// counting; pushing every odd 16th late is what makes a beat walk. 0.58 +// is a light shuffle — 0.5 is dead straight, 0.667 is full triplet swing — +// and it applies to everything that lands off the beat, so the kit, the +// bassline and the stabs all lean the same way rather than fighting. +#define SWING 0.575 +static double sw(double step16) { // a 16th step index → seconds + double beat = floor(step16 / 2.0), odd = fmod(step16, 2.0); + return (beat + (odd ? 2.0 * SWING : 0.0)) * BEAT; +} + +// …and LEAN is the second half. A player does not vary each hit at +// random, they push through one bar and drag through the next: the error +// is CORRELATED, and that is what random jitter can never sound like. Two +// slow incommensurate waves plus a little noise, in milliseconds. +static double lean(double bar, double beat) { + double x = bar + beat / 4.0; + return (0.0075 * sin(TAU * x / 7.0) + 0.0042 * sin(TAU * x / 2.6) + + 0.0018 * sin(TAU * x / 1.37)); +} static uint32_t nseed = 20210725u; static double nrnd(void) { nseed ^= nseed << 13; nseed ^= nseed >> 17; nseed ^= nseed << 5; @@ -226,12 +280,15 @@ } static int missingN = 0; // ── the one-shot player (render3's shot(), ported) ───────────────────── +// `rate` is the playback speed and `rate_to` where it ends up: 1.0 plays +// the sample as recorded, 0.7 plays it slow AND low — which is the whole +// of "screwed", one number. Ramping between the two is a tape stop. typedef struct { - double gain, pan, side, dark, dur, dly, rvb, off, attack; + double gain, pan, side, dark, dur, dly, rvb, off, attack, rate, rate_to; int bus, rev; } Shot; static Shot shot_defaults(void) { - Shot o = { 1, 0, 0.35, 0, 0, 0, 0, 0, 0.0015, BUS_VOX, 0 }; + Shot o = { 1, 0, 0.35, 0, 0, 0, 0, 0, 0.0015, 1.0, 0.0, BUS_VOX, 0 }; return o; } static void shot(const char *name, double t, const Shot *o) { @@ -241,7 +298,13 @@ long start = lround(o->off * SR); if (start < 0) start = 0; if (start > s->n - 2) start = s->n - 2; long avail = o->rev ? (start ? start : s->n - 2) : (s->n - 2 - start); - long n = o->dur > 0 ? (long)fmin((double)avail, o->dur * SR) : avail; + double r0 = o->rate > 0 ? o->rate : 1.0; + double r1 = o->rate_to > 0 ? o->rate_to : r0; + // slower playback covers less tape in the same time, so a screwed slice + // of a given SOURCE length occupies more output than it used to + double rmid = 0.5 * (r0 + r1); + long n = o->dur > 0 ? (long)fmin(avail / fmax(rmid, 1e-6), o->dur * SR) + : (long)(avail / fmax(rmid, 1e-6)); if (n <= 4) return; long i0 = lround(t * SR); Spatial sp = spatial(o->pan * 1.2); @@ -256,56 +319,262 @@ if (o->dark > 0) { lp += (1 - o->dark) * (v - lp); v = lp; } double env = smoothstep((i / (double)SR) / o->attack); emit(o->bus, i0 + i, v * env * o->gain * tail_fade(i, n), o->pan, &sp, o->side, o->dly, o->rvb); - pos += o->rev ? -1.0 : 1.0; + double r = r0 + (r1 - r0) * (i / (double)n); + pos += o->rev ? -r : r; } } // lead + halo + optional backup, all locked to the same chart warp static void sung(const char *name, double t, double gain, double pan, double dly) { Shot o = shot_defaults(); - o.gain = gain; o.pan = pan; o.side = 0.5; o.dly = dly; o.rvb = 0.28; + // more room, more repeat: what puts a voice BEHIND the band is the + // ratio of what you hear directly to what you hear off the walls. + o.gain = gain; o.pan = pan; o.side = 0.5; + o.dly = dly > 0 ? dly + 0.14 : 0.0; o.rvb = 0.58; shot(name, t, &o); } -static void halo(const char *name, double t, double g) { - char nm[96]; +// the chart placer: subtracts the phrase's consonant lead-in so word 0 +// lands ON the beat +static const ChartPhrase *phrase_of(const char *name) { + for (int i = 0; i < CHART_N; i++) + if (!strcmp(CHART[i].name, name)) return &CHART[i]; + fprintf(stderr, " ! no chart phrase %s\n", name); exit(1); +} + +// ONE VOICE. The halo and the backup 3rd/5th used to hang off every call +// here; @jeffrey: "lets not have background vocals anymore". There is +// nothing to fade down to zero — the layers are not built and not sung. +static void voice_line(const char *name, double bar, double gain) { + const ChartPhrase *p = phrase_of(name); + sung(name, at(bar) - p->leadIn, gain, 0, 0.13); +} +// ── the vibraphone ──────────────────────────────────────────────────── +// @jeffrey: "maybe we should add more instruments · more vibes". Taken +// literally, and it is the right instrument for this record: the bank is +// all struck-and-decaying already (pluck, fembell) or all sustain (pads), +// and a vibraphone sits exactly between them. What makes one recognisable +// is not its spectrum, it is the MOTOR — rotating discs over the +// resonators chopping the sound about six times a second — so the tremolo +// is the point and the partials are just a bar being hit. +static void vibe(double t, double st, double dur, double gain, double pan) { + double ring = fmin(dur * 1.6 + 0.9, 4.2); + long n = lround(ring * SR), i0 = lround(t * SR); + Spatial sp = spatial(pan * 1.2); + double f = hz_of(st); + double p1 = 0, p2 = 0, p3 = 0, trem = 0; + for (long i = 0; i < n; i++) { + double u = i / (double)SR; + p1 += (TAU * f) / SR; + p2 += (TAU * f * 4.0) / SR; // the bar's strong 4th partial + p3 += (TAU * f * 9.2) / SR; // and the metallic one, brief + trem += (TAU * 5.6) / SR; + double body = sin(p1) + 0.30 * sin(p2) * exp(-u * 2.6) + + 0.10 * sin(p3) * exp(-u * 11.0); + double env = smoothstep(u / 0.006) * exp(-u * (1.5 + 0.9 / fmax(dur, 0.2))); + double motor = 1.0 - 0.42 * (0.5 - 0.5 * cos(trem)); + emit(BUS_MUSIC, i0 + i, body * 0.30 * env * motor * gain * tail_fade(i, n), + pan, &sp, 0.7, 0.14, 0.44); + } +} + +// ── a word, on its own ──────────────────────────────────────────────── +// @jeffrey: "can 'patiently' especially 'pa' be cooler". Every unit of the +// chart knows its label and its beat, and shot() already takes an offset +// and a length, so any single word can be lifted straight out of the +// rendered line and played again. `pa` is the one big gesture in the take +// — an 8.4-semitone scoop the glide guard deliberately leaves unsnapped — +// and it goes past in half a bar. This gives it the treatment it deserves. +static const ChartNote *unit_named(const ChartPhrase *p, const char *label) { + for (int i = 0; i < p->n; i++) + if (!strcmp(p->notes[i].t, label)) return &p->notes[i]; + fprintf(stderr, " ! no unit %s in %s\n", label, p->name); exit(1); +} +// THE THROW — the word again, an octave up, thrown at the delay and gone. +// Nothing is doubled underneath it: the line has already moved on, so what +// answers back is the scoop alone, arriving off the beat. +static void word_throw(const char *phrase, const char *label, double bar, + double gain, double late, double pan) { + const ChartPhrase *p = phrase_of(phrase); + const ChartNote *n = unit_named(p, label); Shot o = shot_defaults(); - o.side = 0.9; o.rvb = 0.62; o.attack = 0.35; o.bus = BUS_VOX; - snprintf(nm, sizeof nm, "%s-8ve-a", name); - o.gain = g; o.pan = -0.55; o.dly = 0.20; shot(nm, t + 0.028, &o); - snprintf(nm, sizeof nm, "%s-8ve-b", name); - o.gain = g * 0.92; o.pan = 0.55; o.dly = 0.24; shot(nm, t + 0.041, &o); + o.off = p->leadIn + n->beat * BEAT; + o.dur = n->dur * BEAT * 1.15; + o.gain = gain; o.pan = pan; o.side = 0.85; + o.dly = 0.62; o.rvb = 0.55; o.dark = 0.30; o.attack = 0.010; + shot(phrase, at(bar) - p->leadIn + n->beat * BEAT + late, &o); +} +// THE STUTTER — the first 80 ms of the word, three times on 16ths, walking +// up in level so the word itself is the fourth and loudest hit. It runs +// BEFORE the word, so the line is not interrupted; the scoop is announced. +static void word_stutter(const char *phrase, const char *label, double bar, + double gain, double pan) { + const ChartPhrase *p = phrase_of(phrase); + const ChartNote *n = unit_named(p, label); + double t0 = at(bar) - p->leadIn + n->beat * BEAT; + for (int k = 0; k < 3; k++) { + Shot o = shot_defaults(); + o.off = p->leadIn + n->beat * BEAT; + o.dur = 0.080; + o.gain = gain * (0.42 + 0.24 * k); + o.pan = pan * ((k % 2) ? -1 : 1); + o.side = 0.75; o.dly = 0.28; o.rvb = 0.22; o.attack = 0.004; + shot(phrase, t0 - (3 - k) * (BEAT / 4.0), &o); + } } -static void backup(const char *name, double t, double g, int five) { - char nm[96]; + +// ── A GHOST OF A WORD ───────────────────────────────────────────────── +// One word, slowed and soaked, at the level of something remembered +// rather than sung. The intro is built out of these: @jeffrey, "can the +// intro be more / have more previews". A preview is not a quieter copy of +// the section it announces, it is a GLIMPSE — the right length is one +// word, and the right level is under the band. +static void ghost_word(const char *phrase, const char *label, double t, + double rate, double gain, double pan) { + const ChartPhrase *p = phrase_of(phrase); + const ChartNote *nn = unit_named(p, label); Shot o = shot_defaults(); - o.side = 0.7; o.rvb = 0.45; o.attack = 0.06; o.dark = 0.25; - snprintf(nm, sizeof nm, "%s-low3", name); - o.gain = g; o.pan = -0.3; o.dly = 0.12; shot(nm, t, &o); - if (five) { - snprintf(nm, sizeof nm, "%s-low5", name); - o.gain = g * 0.8; o.pan = 0.3; o.dly = 0.14; shot(nm, t, &o); + o.off = p->leadIn + nn->beat * BEAT; + o.dur = nn->dur * BEAT * 1.4; + o.rate = rate; + o.gain = gain; o.pan = pan; o.side = 0.9; + o.dly = 0.52; o.rvb = 0.66; o.dark = 0.42; o.attack = 0.06; + shot(phrase, t, &o); +} + +// ── THE SCRATCH ─────────────────────────────────────────────────────── +// @jeffrey: "and scratches and stuff". A scratch is not a sound, it is a +// GESTURE: the same fragment of record dragged forward and back under the +// hand, so what you hear is one slice played at a shifting rate in +// alternating directions. shot() has both now, so this is the technique +// itself rather than an imitation of it — a baby scratch is `n` passes, +// each one faster and shorter than the last. +static void scratch(const char *phrase, const char *label, double t, + int passes, double gain, double pan) { + const ChartPhrase *p = phrase_of(phrase); + const ChartNote *nn = unit_named(p, label); + double cur = t; + for (int k = 0; k < passes; k++) { + double span = 0.13 / (1.0 + 0.42 * k); // tightening + double rate = 0.85 + 0.55 * k; // …and speeding up + Shot o = shot_defaults(); + o.off = p->leadIn + nn->beat * BEAT + 0.05; + o.dur = span; + o.rate = rate; o.rate_to = rate * (k % 2 ? 0.72 : 1.28); + o.rev = k % 2; // …dragged back + o.gain = gain * (0.68 + 0.32 * (k / (double)passes)); + o.pan = pan * ((k % 2) ? -0.7 : 1.0); + o.side = 0.9; o.dly = 0.24; o.rvb = 0.16; o.attack = 0.002; + shot(phrase, cur, &o); + cur += span; } } -// the chart placer: subtracts the phrase's consonant lead-in so word 0 -// lands ON the beat -static const ChartPhrase *phrase(const char *name) { - for (int i = 0; i < CHART_N; i++) - if (!strcmp(CHART[i].name, name)) return &CHART[i]; - fprintf(stderr, " ! no chart phrase %s\n", name); exit(1); + +// ── THE RISER ───────────────────────────────────────────────────────── +// Deleted with the rest of the ornaments when the kit was stripped, and +// wanted back now — @jeffrey: "and more epic drop". Noise through a +// bandpass that climbs, with the whole thing swelling: the oldest way of +// making a bar feel like it is about to end. +static void riser(double t, double dur, double gain) { + long n = lround(dur * SR), i0 = lround(t * SR); + double bp = 0, bp2 = 0; + for (long i = 0; i < n; i++) { + double u = i / (double)SR, f = u / dur; + double hz = 300.0 * pow(38.0, f); + double k = 1 - exp((-TAU * hz) / SR); + double k2 = 1 - exp((-TAU * hz * 0.55) / SR); + double w = nrnd(); + bp += k * (w - bp); bp2 += k2 * (w - bp2); + double env = f * f * (0.35 + 0.65 * (0.5 - 0.5 * cos(TAU * 5.0 * u))); + emit(BUS_DRUMS, i0 + i, (bp - bp2) * 1.5 * env * gain * tail_fade(i, n), + 0.1 * sin(TAU * 0.7 * u), NULL, 0, 0.10, 0.42); + } } -static void voice_line(const char *name, double bar, double gain, - double haloG, double backupG, int five) { - const ChartPhrase *p = phrase(name); - double t = at(bar) - p->leadIn; - sung(name, t, gain, 0, 0.13); - if (haloG > 0) halo(name, t, haloG); - if (backupG > 0) backup(name, t, backupG, five); + +// ── THE SCREW DOWN ──────────────────────────────────────────────────── +// The tape stopping. One long slice whose rate ramps to a crawl, so the +// pitch falls with it — which is the whole trick of "screwed", and the +// reason it belongs in front of a drop: everything sags, and then the +// floor comes back at full speed. +static void screw_down(const char *phrase, const char *label, double t, + double dur, double gain) { + const ChartPhrase *p = phrase_of(phrase); + const ChartNote *nn = unit_named(p, label); + Shot o = shot_defaults(); + o.off = p->leadIn + nn->beat * BEAT; + o.dur = dur; + o.rate = 1.0; o.rate_to = 0.34; + o.gain = gain; o.side = 0.8; o.dly = 0.40; o.rvb = 0.52; + o.dark = 0.30; o.attack = 0.02; + shot(phrase, t, &o); +} + +// ── THE VOCAL BREAK ─────────────────────────────────────────────────── +// @jeffrey: "cooler vocal breaks". Two bars where the band steps out of +// the way and the words come back chopped: 16th slices of a handful of +// units, accelerating, each one thrown further into the delay than the +// last, so the section is a voice disintegrating rather than a gap. The +// kick keeps running underneath — @jeffrey, earlier: "once the beat / +// kick starts it shouldn't stop it should run through the whole time" — +// and it is the hats and claps that clear out, which is what makes the +// return of the full kit land. +static void vocal_break(const char *phrase, double bar, + const char **words, int nw, double gain) { + const ChartPhrase *p = phrase_of(phrase); + // sixteen slices over two bars, tightening from 8ths to 16ths + for (int k = 0; k < 16; k++) { + double frac = k / 15.0; + double step = (k < 6) ? (BEAT / 2.0) : (BEAT / 4.0); + double t = at(bar) + (k < 6 ? k * (BEAT / 2.0) + : 3.0 * BEAT + (k - 6) * (BEAT / 4.0)); + const ChartNote *n = unit_named(p, words[k % nw]); + Shot o = shot_defaults(); + o.off = p->leadIn + n->beat * BEAT; + // slices shorten as the figure tightens, so it stutters rather + // than overlapping into mush + o.dur = fmin(step * 0.92, 0.055 + 0.16 * (1.0 - frac)); + o.gain = gain * (0.42 + 0.58 * frac); + o.pan = ((k % 2) ? 0.34 : -0.34) * (0.4 + 0.6 * frac); + o.side = 0.85; + o.dly = 0.22 + 0.46 * frac; + o.rvb = 0.30 + 0.34 * frac; + o.dark = 0.42 * (1.0 - frac); // opens up as it accelerates + o.attack = 0.004; + // SCREWED, not merely chopped — @jeffrey: "can we make it even + // more chopped and screwed". Every third slice drags: played at + // two-thirds speed it is also six semitones down, which is the + // technique in one number. Every fourth runs backwards. The rest + // stay square so the figure keeps its pulse. + if (k % 3 == 2) { o.rate = 0.66; o.dur *= 1.5; o.gain *= 1.15; } + if (k % 4 == 3) { o.rev = 1; o.rate = 0.84; } + shot(phrase, t, &o); + // …and a double-trigger under the tightest half: the same slice + // again a 32nd later, quieter, which is the hand slipping + if (k >= 10 && (k % 2 == 0)) { + Shot d = o; + d.gain *= 0.5; d.pan = -o.pan; d.rev = 0; d.rate = 1.28; + d.dur = fmin(o.dur, 0.05); + shot(phrase, t + BEAT / 8.0, &d); + } + } +} + +// A DIFFERENT TAKE OF THE SAME SENTENCE. bin/singdub.py warps s- and o- +// onto this chart and writes exactly its 60 beats, starting at beat 0 — +// so there is no consonant runway to subtract the way voice_line does for +// the take the chart was measured FROM. bin/stage-takes.sh has already +// matched the level, so `gain` here means the same thing it means above +// and the swap reads as a change of room, not of volume. +__attribute__((unused)) +static void alt_line(const char *name, double bar, double gain, double side) { + Shot o = shot_defaults(); + o.gain = gain; o.side = side; o.dly = 0.15; o.rvb = 0.36; + shot(name, at(bar), &o); } // ── the kit — four on the floor, synthesized ─────────────────────────── #define MAX_KICKS 2048 static double kickT[MAX_KICKS]; static int kickN = 0; -static const double KSAT_D = 0.999329299739067; // tanh(3.8) +static const double KSAT_24 = 0.983674092938487; // tanh(2.4) // A HARDER KICK, for the speakers it will actually be heard on. // @jeffrey: "can the kick be harder · so i can hear it better on laptop // speakers with the AC on lol". A laptop cannot reproduce 50 Hz at all, @@ -317,20 +586,51 @@ // tighter, the pitch envelope drops faster, and the click is louder, // longer and two-toned instead of a 2 ms blip at 0.07. static void kick(double t, double gain) { if (kickN < MAX_KICKS) kickT[kickN++] = t; - long n = lround(0.34 * SR), i0 = lround(t * SR); + long n = lround(0.46 * SR), i0 = lround(t * SR); // room for the tail double ph = 0, sub = 0, knk = 0; for (long i = 0; i < n; i++) { double u = i / (double)SR; - double f = 50 + 130 * exp(-u * 58); // snappier drop + // DEEPER — @jeffrey: "maybe a deeper kick". The body used to bottom + // out at 50 Hz and get there in 17 ms; it now falls to 38 and takes + // its time about it, which is what a big kick actually is — not + // more level down low but longer SPENT down low. The sub under it + // drops from 45 to 36 Hz and rings twice as long. The knock and the + // click are untouched: they are what carries the kick on a laptop + // speaker, and none of this is audible there at all. + // …AND DEEP FROM THE FIRST SAMPLE — @jeffrey: "it should be deeper + // especially at the beginnign". Measured, the old attack was not + // deep at all: over its first 25 ms only 5% of the energy sat + // under 60 Hz, with 63% at 60–150 and 31% above that. All the low + // end was in the TAIL. A pitch envelope starting at 180 Hz means + // the sound you hear land is a midrange thump and the depth only + // catches up afterwards, which reads as sharp however gently the + // click is treated. It now starts at 112 and settles to 34. + double f = 34 + 78 * exp(-u * 30); ph += (TAU * f) / SR; - sub += (TAU * 45) / SR; + sub += (TAU * 36) / SR; knk += (TAU * 300) / SR; - double env = (0.6 * exp(-u * 30) + 0.5 * exp(-u * 9)) * fmin(1, u / 0.0008); - double body = tanh(sin(ph) * env * 3.8) / KSAT_D; - double low = sin(sub) * exp(-u * 7) * 0.20; - double knock = sin(knk) * exp(-u * 95) * 0.36; // ~10 ms at 300 Hz - double click = exp(-u * 190) * 0.30 * - (sin(TAU * 2400 * u) + 0.7 * sin(TAU * 4300 * u)); + // TOO SHARP — @jeffrey. Three things were making the edge, and all + // three were deliberate once: the drive was pushed to 3.8 (nearly + // a square wave) and the click to 0.30 back when the brief was + // "can the kick be harder · so i can hear it better on laptop + // speakers with the AC on lol". That kick had to fight; this one + // does not — it is deep now, and a deep kick with a square top is + // just a click sitting on a note. + // + // So the drive comes back to 2.4, where the saturation is adding + // harmonics rather than corners; the click drops to a third and + // moves down an octave, from 2.4/4.3 kHz to 1.5/2.7; and the + // attack takes 2.2 ms instead of 0.8, which is the difference + // between a beater and a spike. The knock stays — that is the part + // a laptop can actually reproduce. + double env = (0.6 * exp(-u * 30) + 0.5 * exp(-u * 9)) * fmin(1, u / 0.0022); + double body = tanh(sin(ph) * env * 2.4) / KSAT_24; + // the sub is at full from sample zero — it is the only part of the + // kick that is already low when the hit arrives + double low = sin(sub) * exp(-u * 3.2) * 0.52; + double knock = sin(knk) * exp(-u * 95) * 0.17; // ~10 ms at 300 Hz + double click = exp(-u * 150) * 0.10 * + (sin(TAU * 1500 * u) + 0.7 * sin(TAU * 2700 * u)); emit(BUS_DRUMS, i0 + i, (body + low + knock + click) * 0.86 * gain * tail_fade(i, n), 0, NULL, 0, 0, 0); @@ -357,61 +657,93 @@ emit(BUS_DRUMS, i0 + i, s * 0.46 * gain * fmin(1, u / 0.001) * tail_fade(i, n), pan, &sp, 0.35, 0, 0.06); } } -static void snare(double t, double gain, double pan) { - long n = lround(0.18 * SR), i0 = lround(t * SR); +// airhat — the offbeat open hat, longer and breathier +// @jeffrey: "can we make it cooler? more up beat". The kit stays simple — +// kick, one offbeat hat, clap on 2 and 4 — but a closed hat on every +// offbeat is a metronome. `open` lets the hat RING, and an open hat on the +// offbeat is the oldest lift in house: it pulls the ear onto the "and" +// instead of onto the beat, and the track starts pushing forward rather +// than marking time. +static void airhat(double t, double gain, double pan, int open) { + double ring = open ? 0.38 : 0.14; + double decay = open ? 7.0 : 24.0; + long n = lround(ring * SR), i0 = lround(t * SR); Spatial sp = spatial(pan * 1.2); - double ph = 0, bp = 0, bp2 = 0; - double k = 1 - exp((-TAU * 3200) / SR), k2 = 1 - exp((-TAU * 1200) / SR); + double bp = 0, bp2 = 0; + double k = 1 - exp((-TAU * (open ? 9200 : 10500)) / SR); + double k2 = 1 - exp((-TAU * 7200) / SR); for (long i = 0; i < n; i++) { double u = i / (double)SR; - ph += (TAU * 196) / SR; double w = nrnd(); bp += k * (w - bp); bp2 += k2 * (w - bp2); - double noise = (bp - bp2) * exp(-u * 22); - double knock = sin(ph) * exp(-u * 30) * 0.5; - double s = tanh((noise * 1.6 + knock) * 1.4); - emit(BUS_DRUMS, i0 + i, s * 0.52 * gain * fmin(1, u / 0.001) * tail_fade(i, n), - pan, &sp, 0.3, 0, 0.05); + emit(BUS_DRUMS, i0 + i, + (bp - bp2) * exp(-u * decay) * 1.1 * gain * (open ? 0.86 : 1.0) + * tail_fade(i, n), + pan, &sp, 0.45, 0, open ? 0.10 : 0.03); } } -// tick — a synthesized closed hat: 8 kHz-centred noise, 30 ms -static void tick(double t, double gain, double pan) { - long n = lround(0.030 * SR), i0 = lround(t * SR); + +// ── the snare — brushed, not cracked ────────────────────────────────── +// @jeffrey: "snares too". The old one was deleted with the rest of the +// ornaments when the kit was stripped, and it was a crack: noise through a +// high band with a fast spike, which is the wrong instrument for a record +// that has just spent an evening getting its kick to stop being sharp. +// +// This is a brush instead. The band sits LOW — 190 Hz to 1.4 kHz rather +// than up where a rimshot lives — there is a tuned shell tone under it at +// 185 Hz, and the attack takes 4 ms, so it arrives rather than snapping. +// `wire` is how much snare-wire rattle rides on top; at 0 it is a tom, at +// 1 it is a backbeat, and the ghosts in between are most of the groove. +static void snare(double t, double gain, double wire, double pan) { + long n = lround((0.16 + 0.10 * wire) * SR), i0 = lround(t * SR); Spatial sp = spatial(pan * 1.2); - double bp = 0, bp2 = 0; - double k = 1 - exp((-TAU * 9500) / SR), k2 = 1 - exp((-TAU * 6000) / SR); + double bp = 0, bp2 = 0, sh = 0, sh2 = 0; + double k = 1 - exp((-TAU * 1400.0) / SR), k2 = 1 - exp((-TAU * 190.0) / SR); for (long i = 0; i < n; i++) { double u = i / (double)SR; double w = nrnd(); bp += k * (w - bp); bp2 += k2 * (w - bp2); - emit(BUS_DRUMS, i0 + i, (bp - bp2) * exp(-u * 90) * 1.6 * gain * tail_fade(i, n), - pan, &sp, 0.4, 0, 0); + double brush = (bp - bp2) * exp(-u * (26.0 - 9.0 * wire)); + sh += (TAU * 185.0) / SR; sh2 += (TAU * 262.0) / SR; + double shell = (sin(sh) + 0.45 * sin(sh2)) * exp(-u * 30.0) * 0.42; + double env = fmin(1.0, u / 0.004); + emit(BUS_DRUMS, i0 + i, + (brush * (0.35 + 0.65 * wire) + shell) * 0.55 * env * gain + * tail_fade(i, n), + pan, &sp, 0.5, 0.05, 0.20 + 0.16 * wire); } } -// airhat — the offbeat open hat, longer and breathier -static void airhat(double t, double gain, double pan) { - long n = lround(0.14 * SR), i0 = lround(t * SR); + +// ── the stab — a chord on the offbeat ────────────────────────────────── +// The other half of "more up beat", and it is musical rather than +// percussive: a short filtered chord landing on the "and", which is what +// makes a house record feel like it is leaning forward. Sharp attack, a +// decay under a beat, and a lowpass that opens with the arrangement, so +// the same figure reads as muffled in an early pass and bright in a late +// one. +static void stab(double t, const double *tones, int n_t, double dur, + double gain, double open, double pan) { + long n = lround((dur + 0.10) * SR), i0 = lround(t * SR); Spatial sp = spatial(pan * 1.2); - double bp = 0, bp2 = 0; - double k = 1 - exp((-TAU * 10500) / SR), k2 = 1 - exp((-TAU * 7200) / SR); + double ph[4] = {0, 0, 0, 0}, det[4] = {1.0, 1.0032, 0.9971, 1.0018}; + double lp = 0, lp2 = 0; + double cut = 520.0 + 3400.0 * open; + double k = 1 - exp((-TAU * cut) / SR); for (long i = 0; i < n; i++) { double u = i / (double)SR; - double w = nrnd(); - bp += k * (w - bp); bp2 += k2 * (w - bp2); - emit(BUS_DRUMS, i0 + i, (bp - bp2) * exp(-u * 24) * 1.1 * gain * tail_fade(i, n), - pan, &sp, 0.45, 0, 0.03); - } -} -static void riser(double t, double dur, double gain) { - long n = lround(dur * SR), i0 = lround(t * SR); - double bp = 0; - for (long i = 0; i < n; i++) { - double u = i / (double)n; - double w = nrnd(); - double kf = 1 - exp((-TAU * (600 + 8000 * u * u)) / SR); - bp += kf * (w - bp); - emit(BUS_DRUMS, i0 + i, bp * u * u * gain * tail_fade(i, n), - (u - 0.5) * 0.4, NULL, 0, 0, 0.10); + double env = smoothstep(u / 0.004) * exp(-u * (3.4 / fmax(dur, 0.05))); + double v = 0; + for (int j = 0; j < n_t && j < 4; j++) { + double f = hz_of(tones[j]); + ph[j] += (TAU * f * det[j]) / SR; + // a saw, so the filter has something to bite on + double x = fmod(ph[j] / TAU, 1.0) * 2.0 - 1.0; + v += x; + } + v /= (double)(n_t ? n_t : 1); + lp += k * (v - lp); lp2 += k * (lp - lp2); // 12 dB/oct + emit(BUS_MUSIC, i0 + i, lp2 * 0.5 * env * gain * tail_fade(i, n), + pan, &sp, 0.6, 0.16, 0.30); } } @@ -481,7 +813,7 @@ } // play a chart phrase's melody as pluck notes — the band doubling her, // or answering in the gaps (octave 0 doubles; +12 answers up high) static void pluck_line(const char *name, double bar, double gain, int oct, double pan) { - const ChartPhrase *p = phrase(name); + const ChartPhrase *p = phrase_of(name); for (int i = 0; i < p->n; i++) { const ChartNote *nn = &p->notes[i]; pluck(at(bar) + nn->beat * BEAT + jit(3), nn->st + oct, @@ -489,86 +821,302 @@ nn->dur * BEAT, gain * (1 - 0.03 * i), pan * ((i % 2) ? -1 : 1)); } } -// ── the harp (vox3's arp bank, LCG-swung) ────────────────────────────── -static const int ARP_I[] = { 12, 15, 19, 24, 27 }; -static const int ARP_III[] = { 15, 19, 22, 27 }; -static const int ARP_IV[] = { 17, 20, 24 }; -static const int ARP_VI[] = { 15, 20, 24, 27 }; -static const int ARP_VII[] = { 17, 22, 26 }; -static void arp(double t, const int *tones, int ntones, const char *vowel, - int count, int up, double gap, double gain, double pan) { - for (int k = 0; k < count; k++) { - int st = tones[up ? k % ntones : ntones - 1 - (k % ntones)] - + 12 * (k / ntones) * (up ? 1 : -1); - char nm[32]; snprintf(nm, sizeof nm, "arp-%s-%d", vowel, st); - if (!bank_get(nm)) continue; - Shot o = shot_defaults(); - o.gain = gain * (1 - 0.06 * k); - o.pan = pan * ((k % 2) ? -1 : 1); - o.side = 0.8; o.dly = 0.30; o.rvb = 0.5; o.dur = 0.22; o.attack = 0.022; - shot(nm, t + k * gap + jit(4) + ((k % 2) ? 0.010 : 0), &o); - } -} +// ── FEM bells — the /pop bell voice, in this engine ──────────────────── +// @jeffrey: "lets extend this now a bit and add fem bells · bring in our +// usual /pop sounds". pop/bell/ solves a real shell by finite elements and +// bakes wavs; that is the right tool for a bell record and the wrong one +// for a voice inside a 2-minute dance cut, so this is its OUTPUT shape: a +// modal sum on the partial ratios a struck bell actually has, each partial +// with its own decay and a little beating between a detuned pair. +// +// The house rules from pop/wattajetta come with it, and they are rules +// because breaking them made that record tangy on a laptop: +// · runs stay at or under E5 — see BELL_CEIL_ST +// · bells NEVER pass through saturation; this writes to BUS_MUSIC clean +// · a choked strike gets a real fade, never a truncation +static const double BELL_PARTIAL[6] = { 0.5, 1.0, 1.19, 1.5, 2.0, 2.51 }; +static const double BELL_GAIN[6] = { 0.42, 1.0, 0.55, 0.38, 0.30, 0.14 }; +static const double BELL_DECAY[6] = { 1.6, 2.6, 3.4, 4.2, 5.4, 8.0 }; +// THE CEILING, RAISED. @jeffrey: "lets bring up the fem bel pitch". The +// E5 line came from pop/wattajetta, where E5–E6 runs read "too high and +// tangy on my macbook speakers" — that lesson is about MELODIC bell runs +// carrying the tune, and these are answering a vocal rather than carrying +// it. So the ceiling goes to A5 and the runs start an octave higher, with +// the compensation the same memory prescribes: the sixth octave is for +// SPARKLE, so anything above E5 loses gain rather than keeping it. Bells +// still never touch saturation — that is the part of the rule that is not +// negotiable, and it is why they go straight to BUS_MUSIC. +#define BELL_CEIL_ST 23.0 // A5 in the take's frame +#define BELL_TANG_ST 18.0 // …but above E5 it pays for the altitude -// ── tape ─────────────────────────────────────────────────────────────── -static void hiss_bed(void) { - double lp = 0, hp = 0, prev = 0, lvl = 0.010; - double kLp = 1 - exp((-TAU * 5200) / SR); - double hpRc = 1 / (TAU * 320), hpA = hpRc / (hpRc + 1.0 / SR); - for (long i = 0; i < N; i++) { - double bar = i / (double)SR / BAR; - double target = bar < 32 ? 0.0040 : bar < 40 ? 0.0095 : - bar < 60 ? 0.0040 : 0.011; - lvl += 0.000004 * (target - lvl); - double w = nrnd(); - lp += kLp * (w - lp); - hp = hpA * (hp + lp - prev); prev = lp; - musicL[i] += hp * lvl; musicR[i] += hp * lvl * 0.94; +static void fembell(double t, double st, double dur, double gain, double pan) { + while (st > BELL_CEIL_ST) st -= 12; // the ceiling is not optional + if (st > BELL_TANG_ST) // sparkle, not melody + gain *= 1.0 - 0.42 * ((st - BELL_TANG_ST) / (BELL_CEIL_ST - BELL_TANG_ST)); + double ring = fmin(dur * 1.4 + 0.5, 3.2); + long n = lround(ring * SR), i0 = lround(t * SR); + Spatial sp = spatial(pan); + double f = hz_of(st); + double ph[6][2] = {{0}}; + // the strike: a short bright contact before the modes take over + long nc = lround(0.006 * SR); + for (long i = 0; i < n; i++) { + double u = i / (double)SR; + double s = 0; + for (int k = 0; k < 6; k++) { + double fk = f * BELL_PARTIAL[k]; + ph[k][0] += (TAU * fk) / SR; + ph[k][1] += (TAU * fk * 1.0018) / SR; // the beat in a real bell + s += BELL_GAIN[k] * exp(-u * BELL_DECAY[k]) + * (sin(ph[k][0]) + 0.8 * sin(ph[k][1])); + } + s /= 3.4; + if (i < nc) s += 0.30 * (rnd() * 2 - 1) * (1 - i / (double)nc); + // a truncated ring clicks — fade the last 80 ms, always + double env = 1.0; + double left = (n - i) / (double)SR; + if (left < 0.080) env = left / 0.080; + emit(BUS_MUSIC, i0 + i, s * env * gain * tail_fade(i, n), pan, &sp, + 0.45, 0.18, 0.42); } } -static void dust(double t, double gain) { - long n = lround(0.0022 * SR), i0 = lround(t * SR); - for (long i = 0; i < n; i++) - emit(BUS_MUSIC, i0 + i, nrnd() * exp(-i / (0.0006 * SR)) * gain, - nrnd() * 0.5, NULL, 0, 0, 0); -} + + // ── harmony — the v3 chords on a one-bar dance rhythm ────────────────── -typedef struct { double root; double tones[3]; } Chord; -static const Chord CH_i = { 0, { 0, 3, 7 } }; -static const Chord CH_III = { 3, { 3, 7, 10 } }; -static const Chord CH_VI = { -4, { -4, 0, 3 } }; -static const Chord CH_VII = { -2, { -2, 2, 5 } }; +// …and the SEVENTH. @jeffrey: "more jazz". A triad is a fact; a seventh is +// an opinion. These are the same four chords the record has always used — +// nothing about the harmony moves — but each now carries the note that +// makes it lean somewhere: minor sevenths on i and VI, a major seventh on +// III where the tune is already at its brightest, and a ninth on VII +// because it is the turnaround and wants to be unresolved. Only the stab +// and the pad reach for it; the bass and the bells stay on the triad, so +// the colour arrives without the bottom getting muddy. +typedef struct { double root; double tones[3]; double sev; } Chord; +static const Chord CH_i = { 0, { 0, 3, 7 }, 10 }; // i7 +static const Chord CH_III = { 3, { 3, 7, 10 }, 14 }; // III maj7 → 9 +static const Chord CH_VI = { -4, { -4, 0, 3 }, 6 }; // VI7 +static const Chord CH_VII = { -2, { -2, 2, 5 }, 9 }; // VII add9 // per section: 8-bar rows (dance harmonic rhythm: one chord per bar) static const Chord *ROW_VERSE[8] = { &CH_i, &CH_i, &CH_VI, &CH_VI, &CH_III, &CH_III, &CH_VII, &CH_VII }; static const Chord *ROW_HOOK[8] = { &CH_VI, &CH_VII, &CH_i, &CH_i, &CH_VI, &CH_VII, &CH_III, &CH_VII }; static const Chord *ROW_BREAK[8] = { &CH_i, &CH_i, &CH_VI, &CH_VI, &CH_i, &CH_i, &CH_VII, &CH_VII }; +// LONERCLUB, the narrative — @jeffrey: "i want our mix to have drops and +// arepggios · and like nice overall narrative · lets call the track +// Lonerclub". Every block that holds the whole take is SIXTEEN bars now: +// the charted line runs 60 beats, and the old 12-bar blocks made her +// sing straight through the section after her. +// +// SIX PASSES, AND THE LEAD CHANGES HANDS. @jeffrey: "lets work on swap +// lead and also use / bring in group takes · but the idea is we start +// small with camille's softest take then we build up each one · maybe +// even alonging / getting things longer a bit". The takes were MEASURED +// and they already form the arc: f −22.1 LUFS (the Feral spine, softest, +// solo), s −16.8 (roomier and lower, solo), o −12.2 (the ensemble, with +// @jeffrey and Alex). So the record starts on the quietest thing she ever +// sang and ends with a room full of people singing it. +// +// L1 0–16 0:00 f- alone. No harmony at all. +// L2 16–32 0:31 f- and her low 3rd +// L3 32–48 1:03 the S TAKE takes the lead — floor thins, kick stays +// L4 48–64 1:34 f- back, 3rd and 5th, bells arpeggiating +// L5 64–80 2:06 the GROUP take leads. The club sings it. +// L6 80–96 2:37 the ghost, thinning to the pluck alone static const Chord *chord_at(int bar) { - if (bar < 12) return ROW_VERSE[bar % 8]; - if (bar < 20) return ROW_HOOK[bar % 8]; - if (bar < 28) return ROW_VERSE[bar % 8]; - if (bar < 40) return ROW_BREAK[bar % 8]; - if (bar < 58) return (bar < 52) ? ROW_VERSE[bar % 8] : ROW_HOOK[bar % 8]; - return ROW_BREAK[bar % 8]; + int b = bar - INTRO; // the intro rides L1's changes + if (b < 0) b += 16; + if (b < 16) return ROW_VERSE[b % 8]; + if (b < 32) return ROW_HOOK[b % 8]; + if (b < 48) return ROW_BREAK[b % 8]; + if (b < 64) return ROW_VERSE[b % 8]; + if (b < 80) return ROW_HOOK[b % 8]; + return ROW_BREAK[b % 8]; } static int kick_on(int bar) { // the strict floor: where it runs - return !(bar >= 28 && bar < 40) && bar < 72; + return !(bar >= L(2) && bar < L(3)) && bar < BARS - 4; +} + +// A bell RUN — chord tones climbing from the tonic, swung a little so it +// rolls rather than marches. This is the arpeggio @jeffrey asked the mix +// for ("i want our mix to have drops and arepggios"), played by the bell. +static void bell_run(double t, const Chord *c, int count, double step, + double gain, int up, double pan) { + for (int k = 0; k < count; k++) { + int idx = up ? k : count - 1 - k; + double st = c->tones[idx % 3] + 12 * (idx / 3) + 12; + fembell(t + k * step + ((k % 2) ? step * 0.08 : 0) + jit(3), + st, step * 1.6, gain * (1 - 0.05 * k), + pan * ((k % 2) ? -1 : 1)); + } +} + +// ── THE HOOK ────────────────────────────────────────────────────────── +// @jeffrey: "our instrumentation should be smarter compositionally / more +// structured". What it was doing was texture: every part played all the +// time inside its section, the pluck doubled her line in unison, and the +// bells ran the same arpeggio whatever bar they were in. Nothing was ever +// STATED, so nothing could be answered or returned to. +// +// This is the figure the record quotes. It is the first four notes of her +// own melody — 7 5 3 2, the descent under "sit-ting curled up" — because a +// hook the band invents is decoration, and a hook lifted from the singer +// is the song. It is stated at the head of a phrase and ANSWERED four bars +// later by its inversion, which is the oldest structure there is: +// antecedent, then consequent. +static const int HOOK[4] = { 7, 5, 3, 2 }; +static const int HOOK_ANS[4] = { 2, 3, 5, 7 }; +enum { VOICE_PLUCK, VOICE_VIBE, VOICE_BELL }; + +static void hook_say(double t, const int *fig, int oct, int voice, + double gain, double pan) { + for (int k = 0; k < 4; k++) { + double u = t + k * (BEAT / 2.0) + jit(4); + double st = fig[k] + oct; + double p = pan * ((k % 2) ? -0.6 : 1.0); + switch (voice) { + case VOICE_VIBE: vibe(u, st, 0.9, gain, p); break; + case VOICE_BELL: fembell(u, st, 1.1, gain * 0.8, p); break; + default: pluck(u, st, 0.75, gain, p); break; + } + } +} + +// THE TURNAROUND. Eight-bar rows that simply repeat have no edge to them; +// this marks bar 7 of each row so the ear can hear a phrase close and +// another begin. It is the VII chord walking up into the downbeat — the +// one place in the harmony that is already unresolved. +static void turnaround(double bar, double gain) { + static const int UP[3] = { -2, 2, 5 }; + for (int k = 0; k < 3; k++) + pluck(at(bar) + (2.0 + k * 0.5) * BEAT + jit(4), UP[k] + 12, + 0.5, gain * (0.7 + 0.15 * k), (k % 2) ? 0.30 : -0.26); + fembell(at(bar) + 3.5 * BEAT, 9, 0.9, gain * 0.5, 0.2); +} + + +// ── the backing voice — one sine, one note at a time, under her ──────── +// @jeffrey: "canwe start to bring in piano / sine pad accompaniment · +// just a single voice to back the vocal". Deliberately NOT the chord +// stack the bed already plays: one voice, held, moving as little as the +// harmony will let it and re-articulating only when it has to move. It +// lives in the octave under her lowest sung note (G#3), so it holds the +// chord up without ever arriving in the same place as a word — and it is +// `pad()` with nst = 1, which is already a detuned sine pair under a +// tape-wow lid, rather than a second synth doing the same job. +// The register. It was A#2–G3 (103–195 Hz) — genuinely under her, and +// genuinely inaudible on anything without a woofer: @jeffrey, "im not +// hearing those instruments". Moved up a fifth into the range a laptop +// and a phone actually reproduce, still below her sung line (her lowest +// is G#3, −5, and she spends the song above it). +#define BACK_LO (-7.0) // F3 up to C4 +#define BACK_HI (3.0) +static double backing_note(const Chord *c, double from, int first) { + double best = BACK_LO, bestd = 1e9; + for (int k = 0; k < 3; k++) + for (int oct = -2; oct <= 1; oct++) { + double st = c->tones[k] + 12 * oct; + if (st < BACK_LO || st > BACK_HI) continue; + // voice-leading: the nearest tone to where the voice already + // is. Only the first note is placed by register instead. + double d = first ? fabs(st + 9) : fabs(st - from); + if (d < bestd) { bestd = d; best = st; } + } + return best; +} +// One call per HELD note, not per bar — a bar whose chord keeps the +// voice's note just lets it ring rather than striking it again. +static void backing_line(int bar0, int bars, double off, double gain) { + double cur = 0; + int start = -1; + for (int bar = 0; bar <= bars; bar++) { + double st = 0; + int have = bar < bars; + if (have) st = backing_note(chord_at(bar0 + bar), cur, start < 0); + if (start >= 0 && (!have || st != cur)) { + pad(off + at(bar0 + start), &cur, 1, (bar - start) * BAR - 0.06, + gain, 0.55, 0.0, 0.35, 0.08, 0.26); + start = -1; + } + if (have && start < 0) { cur = st; start = bar; } + } } // ── the floor — one bar of the dance kit ─────────────────────────────── -static const double VEL[16] = { 1, 0.45, 0.7, 0.5, 0.9, 0.45, 0.72, 0.5, - 1, 0.45, 0.7, 0.5, 0.85, 0.5, 0.78, 0.55 }; -static void floor_bar(int bar, double kickG, double hatG, int claps, int fills) { +// @jeffrey: "simple perc". Kick on the four, one hat on the offbeat, a +// clap on 2 and 4. The 16th-note tick bed, the snare backbeat, the fills +// and the risers are gone. They were the difference between a track that +// moves and a track that is busy, and every one of them lived in the same +// 4–8 kHz band as her consonants. +// VELOCITY, as a player would place it. Four identical kicks a bar is the +// machine; a drummer leans on 1, lets 2 breathe, half-leans on 3. The +// pattern repeats over two bars so it is a groove and not a wobble. +static const double KV[8] = { 1.00, 0.90, 0.96, 0.88, 0.98, 0.87, 0.94, 0.91 }; +static const double HV[8] = { 0.92, 1.00, 0.86, 0.97, 0.95, 1.00, 0.84, 0.99 }; + +static void floor_bar(int bar, double kickG, double hatG, int claps) { double t = at(bar); - for (int b = 0; b < 4; b++) kick(t + b * BEAT, kickG * (b == 0 ? 1.0 : 0.94)); - if (claps) { clap(t + 1 * BEAT, 0.85, 0.08); clap(t + 3 * BEAT, 0.82, -0.06); } - for (int b = 0; b < 4; b++) airhat(t + (b + 0.5) * BEAT, 0.16, (b % 2) ? 0.3 : -0.3); - for (int s = 0; s < 16; s++) tick(t + s * STEP + jit(2), hatG * VEL[s], (s % 2) ? 0.3 : -0.24); - if (fills && bar % 4 == 3) { - snare(t + 14 * STEP, 0.30, 0.2); - snare(t + 15 * STEP, 0.36, -0.15); + for (int b = 0; b < 4; b++) { + double d = lean(bar, b); + kick(t + b * BEAT + d, kickG * KV[(bar * 4 + b) % 8]); + } + if (claps) { + // the clap lands a hair LATE, always — it is the one thing in a + // house bar that is allowed to be behind the beat, and it is most + // of what makes the two and four feel like a person + clap(t + 1 * BEAT + lean(bar, 1) + 0.010, 0.66, 0.08); + clap(t + 3 * BEAT + lean(bar, 3) + 0.013, 0.64, -0.06); + } + // the "and" of 2 and 4 rings; the other two stay closed — and every + // one of them is SWUNG, so the offbeat arrives late the way a + // shuffle does rather than exactly halfway + for (int b = 0; b < 4; b++) + airhat(t + sw(b * 2 + 1) + lean(bar, b + 0.5), + hatG * HV[(bar * 4 + b) % 8], (b % 2) ? 0.28 : -0.24, b % 2); + // GHOST HATS on the last 16th of every other beat: barely there, + // swung with everything else, and the reason the bar has an inside. + for (int b = 0; b < 4; b++) { + if ((bar + b) % 2) continue; + airhat(t + sw(b * 2 + 1.5) + lean(bar, b + 0.75), + hatG * 0.34, (b % 2) ? -0.36 : 0.34, 0); + } + // GHOST SNARES — the brush, under everything, on the 16ths a drummer + // fills with their left hand. Never on 2 and 4: the clap owns those, + // and doubling them would just make the backbeat louder rather than + // making the bar breathe. + if (claps) { + snare(t + sw(2.5) + lean(bar, 1.25), 0.16, 0.30, -0.22); + snare(t + sw(6.5) + lean(bar, 3.25), 0.13, 0.26, 0.24); + if (bar % 4 == 3) { + snare(t + sw(6) + lean(bar, 3.0), 0.22, 0.55, 0.10); + snare(t + sw(7) + lean(bar, 3.5), 0.30, 0.75, -0.12); + } + } + + // ── POLYRHYTHM ──────────────────────────────────────────────────── + // @jeffrey: "and polythyrhtms!". Two of them, both against the same + // 4/4 floor and neither of them agreeing with it: + // + // THREE against four — a brush every 3 sixteenths. Sixteen 16ths in + // a bar and a period of 3 means the pattern only lands on the + // downbeat again every THREE bars, so the same figure keeps + // arriving somewhere new. + // FIVE against four — a closed hat every 5 sixteenths, which takes + // FIVE bars to come round. The two cycles agree once every fifteen. + // + // Both are quiet. A polyrhythm you can pick out is a competing beat; + // one you can only feel is a groove. + { + long step = (long)bar * 16; + for (int q = 0; q < 16; q++) { + long g = step + q; + if (g % 3 == 0) + snare(t + sw(q) + lean(bar, q / 4.0), 0.085, 0.16, + (g % 6) ? 0.40 : -0.40); + if (g % 5 == 0) + airhat(t + sw(q) + lean(bar, q / 4.0), hatG * 0.30, + (g % 10) ? -0.42 : 0.42, 0); + } } - if (bar % 2 == 1) snare(t + 7 * STEP, 0.20, -0.2); } // ── sidechain — the pump, keyed by every kick ────────────────────────── @@ -597,7 +1145,7 @@ // ═══ main ══════════════════════════════════════════════════════════════ static int minimal_bars(void) { // the line once, plus a bar to breathe — and never past bar 16 // (@jeffrey: "no need to go past bar 16"); the line ends inside 15. - int b = (int)(ceil(phrase("w-whole-line")->beats / 4.0) + 2); + int b = (int)(ceil(phrase_of("w-whole-line")->beats / 4.0) + 2); return b < 16 ? b : 16; } @@ -606,9 +1154,12 @@ // MINIMAL=1 → the study pass: kick + the unbroken vocal, nothing // else — "lets start with just kick and vocals and get that right". int minimal = getenv("MINIMAL") != NULL; BEAT = 60.0 / BPM; BAR = 4 * BEAT; STEP = BEAT / 4; + // exactly the runway the first sung phrase needs, and not a sample + // more — see the note above at(). + PREROLL = INTRO > 0 ? 0.0 : phrase_of("w-whole-line")->leadIn; // the study stops at bar 16 and needs only enough tail for the last // note to ring — six seconds of nothing was six seconds of watching - N = lround(((minimal ? minimal_bars() : BARS) * BAR + N = lround((PREROLL + (minimal ? minimal_bars() : BARS) * BAR + (minimal ? 2.0 : TAIL_S)) * SR); drumsL = calloc(N, 4); drumsR = calloc(N, 4); musicL = calloc(N, 4); musicR = calloc(N, 4); @@ -630,7 +1181,14 @@ // NO COUNT-IN — the file opens on her pickup. The render starts // at the /s/ of "sitting"; the phrase's beat 0, and the first // kick with it, land one lead-in later, so the downbeat IS the // first word rather than the third bar of waiting. - const ChartPhrase *p = phrase("w-whole-line"); + // WHOSE CHART GOVERNS THE STUDY. Each take now has one of its own + // (bin/takechart.py), and its leadIn is its own measured consonant + // runway — 0.37 beats for s-, 0.84 for sh-. Reading f-'s here + // would put every other take's pickup in the wrong place, which + // is the borrowed-envelope problem the takecharts exist to end. + const char *takeEnv = getenv("TAKE"); + const char *takePhrase = (takeEnv && *takeEnv) ? takeEnv : "w-whole-line"; + const ChartPhrase *p = phrase_of(takePhrase); double lineBars = ceil(p->beats / 4.0); int kickBars = (int)(lineBars + 1); if (kickBars > 16) kickBars = 16; @@ -645,14 +1203,58 @@ // give the subdivision the words are actually being placed on. // no pickup kick — there is no pickup beat any more for (int bar = 0; bar < kickBars; bar++) { double t = off + at(bar); - for (int b = 0; b < 4; b++) kick(t + b * BEAT, 0.95); + for (int b = 0; b < 4; b++) kick(t + b * BEAT, 0.62); for (int b = 0; b < 4; b++) - airhat(t + (b + 0.5) * BEAT, 0.15, (b % 2) ? 0.3 : -0.3); - for (int s = 0; s < 16; s++) - tick(t + s * STEP, (s % 4 == 0) ? 0.10 : 0.05, - (s % 2) ? 0.28 : -0.22); + airhat(t + (b + 0.5) * BEAT, 0.14, (b % 2) ? 0.3 : -0.3, b % 2); + } + // the backing voice, under the words — one held note at a time + backing_line(0, kickBars, off, 0.55); + // …and the bed under THAT — @jeffrey: "and also lets add the synth + // pads / sine accompaniment now!". The full mix's voicing, at study + // level: a low pair on two-bar chords, and the mid triad a beat + // behind it so the chord arrives rather than lands. + for (int bar = 0; bar < kickBars; bar += 2) { + const Chord *c = chord_at(bar); + double lows[3] = { c->root - 24, c->root - 12, c->tones[1] - 12 }; + pad(off + at(bar) + 0.02, lows, 3, 2 * BAR - 0.1, 0.42, 1.1, 0, 0.55, 0, 0.30); + double mids[3] = { c->tones[0], c->tones[1], c->tones[2] }; + pad(off + at(bar) + 0.15, mids, 3, 2 * BAR - 0.3, 0.55, 1.5, 0.18, 0.7, 0.10, 0.36); } - sung("w-whole-line", 0.0, 0.98, 0, 0.0); + // HER MELODY, on the music box — @jeffrey: "lets start working on + // more accompaniment". The pluck plays ONLY charted notes, so the + // band's line IS her line: it doubles under every word and rings + // on through the gaps she leaves. + { + const ChartPhrase *pp = phrase_of("w-whole-line"); + for (int i = 0; i < pp->n; i++) { + const ChartNote *nn = &pp->notes[i]; + // IN OCTAVES — @jeffrey: "i was hoping for notes in the + // octaves · like so we could have the lyrics and melody + // being more closely mapped". Her note, the octave under + // it for weight, and the octave over it for the mapping + // to be unmissable. The low octave leads slightly so the + // top one reads as the melody rather than as a chord. + double t0 = off + nn->beat * BEAT + jit(3); + double d = nn->dur * BEAT; + double pn = (i % 2) ? -0.12 : 0.12; + pluck(t0, nn->st, d, 0.62, pn); + pluck(t0 - 0.006, nn->st - 12, d, 0.30, -pn * 0.5); + pluck(t0 + 0.010, nn->st + 12, d, 0.36, pn * 1.6); + } + } + // and the sub, offbeat, answering each kick + for (int bar = 0; bar < kickBars; bar++) { + const Chord *c = chord_at(bar); + for (int b = 0; b < 4; b++) + bass(off + at(bar) + (b + 0.5) * BEAT, c->root - 24, + 0.30, 0.55, 0.012); + } + // …and TAKE_WAV is what it actually sings, so the study can play a + // level-matched copy of a take while still reading that take's + // own chart. @jeffrey: "see how they sound solo · with mp4 vocal + // tests again?" + const char *wavEnv = getenv("TAKE_WAV"); + sung((wavEnv && *wavEnv) ? wavEnv : takePhrase, 0.0, 0.98, 0, 0.0); goto mixdown; } @@ -661,121 +1263,283 @@ // break gets the slow-attack ballad voicing. for (int bar = 0; bar < BARS - 4; bar++) { const Chord *c = chord_at(bar); double lows[3] = { c->root - 24, c->root - 12, c->tones[1] - 12 }; - int brk = (bar >= 32 && bar < 40), outro = bar >= 60; + int brk = (bar >= L(2) && bar < L(3)), outro = bar >= L(5); if (bar % 2 == 0) { double g = brk ? 0.15 : outro ? 0.13 : 0.16; pad(at(bar) + 0.02, lows, 3, 2 * BAR - 0.1, g, brk ? 2.4 : 1.1, 0, 0.55, 0, 0.30); if (!brk && !outro) { - double mids[3] = { c->tones[0], c->tones[1], c->tones[2] }; - pad(at(bar) + 0.15, mids, 3, 2 * BAR - 0.3, g * 0.68, + double mids[4] = { c->tones[0], c->tones[1], c->tones[2], c->sev }; + pad(at(bar) + 0.15, mids, 4, 2 * BAR - 0.3, g * 0.68, 1.5, 0.18, 0.7, 0.10, 0.36); } } - // THE BASS — offbeat house sub answering every kick + // THE BASS — @jeffrey: "can we make it cooler? more up beat". + // It was four identical offbeat subs a bar, at root−24, which is + // a pad with a rhythm rather than a bassline: nothing in it moves, + // so nothing in it pushes. Now it walks. Root on the offbeats, the + // fifth under beat 3 so the bar turns over, and a 16th PUSH into + // the next downbeat — the note that arrives early is what makes a + // house bar feel like it is falling forward. An octave up on the + // last offbeat of every other bar keeps it from settling. if (kick_on(bar)) { - for (int b = 0; b < 4; b++) - bass(at(bar) + (b + 0.5) * BEAT, c->root - 24, 0.30, 0.9, 0.012); + for (int b = 0; b < 4; b++) { + double st = c->root - 24; + if (b == 2) st = c->tones[2] - 24; // the fifth, mid-bar + if (b == 3 && (bar % 2)) st += 12; // …and a lift out + // swung with the hats: if the bass sat square while the kit + // shuffled they would fight, and the groove would read as + // sloppy rather than as swung + bass(at(bar) + sw(b * 2 + 1) + lean(bar, b + 0.5), st, + 0.30, 0.92 * KV[(bar * 4 + b) % 8], 0.012); + } + // the push: a 16th before the next bar, short and quiet, so the + // downbeat is arrived AT rather than merely landed on + bass(at(bar) + sw(7.5) + lean(bar, 3.75), c->root - 24, + 0.13, 0.62, 0.008); } else { bass(at(bar), c->root - 24, BAR - 0.12, 0.5, 0.045); } } // THE FLOOR + // THE FLOOR NEVER STOPS. @jeffrey: "once the beat / kick starts it + // shouldn't stop it should run through the whole time". The BREAK used + // to take the kick out entirely for sixteen bars — a dance-record + // reflex, and the wrong one here: this is a club cut and the floor is + // the thing you are standing on. So the break still empties, but it + // empties AROUND the kick: no claps, no hats, no ticks, and the kick + // itself pulled back to 0.72 so the room opens without the ground + // disappearing. Everything that made the section an event — the + // harmony thinning, the riser back in — is still there. + // THE VOCAL BREAKS clear the kit for their two bars — no claps, hats + // right down — while the kick keeps running. See vocal_break(). for (int bar = 0; bar < BARS; bar++) { - if (!kick_on(bar)) continue; - double build = bar >= 38 ? 0 : 1; (void)build; - double kg = bar < 12 ? 0.92 : bar < 20 ? 0.98 : bar < 28 ? 0.95 : 1.0; - double hg = bar < 12 ? 0.065 : 0.085; - int claps = bar >= 4; - floor_bar(bar, kg, hg, claps, bar >= 12); + int brk = (bar >= L(2) && bar < L(3)); + int vb = (bar >= L(1) - 2 && bar < L(1)) || (bar >= L(2) - 2 && bar < L(2)) || + (bar >= L(4) - 2 && bar < L(4)) || (bar >= L(5) - 2 && bar < L(5)); + double kg = vb ? 0.82 + : brk ? 0.72 + : bar < L(1) ? 0.88 : bar < L(2) ? 0.95 + : bar < L(5) ? 1.0 : 0.84; + double hg = vb ? 0.03 : brk ? 0.05 : bar < L(1) ? 0.10 : 0.15; + int claps = (bar >= L(1)) && !brk && !vb; + floor_bar(bar, kg, hg, claps); } - // the rebuild rush out of the break - riser(at(38), 2 * BAR, 0.26); - for (int s = 0; s < 8; s++) snare(at(39) + (8 + s) * STEP, 0.18 + 0.04 * s, (s % 2) ? 0.25 : -0.25); + { // the words each break is built from — the scoop, the low held + // note, and the last word of the sentence + static const char *W1[] = { "pa", "stone" }; + static const char *W2[] = { "pa", "stone", "pass" }; + static const char *W3[] = { "pa", "think", "stone", "pass" }; + vocal_break("w-whole-line", L(1) - 2, W1, 2, 0.34); + vocal_break("w-whole-line", L(2) - 2, W2, 3, 0.44); + vocal_break("w-whole-line", L(4) - 2, W3, 4, 0.50); + vocal_break("w-whole-line", L(5) - 2, W2, 3, 0.38); + } + // ── LONERCLUB — SIX PASSES OF ONE SENTENCE, ONE VOICE ───────────── + // @jeffrey: "i want to try and just get a real clean track for now... + // simple perc simple vocals... and lets not have background vocals + // anymore". + // + // So every halo, every backup 3rd and 5th, every "ah"/"oh" arp and + // every ensemble texture shot is gone. What is left is HER LINE, sung + // whole, six times, and a band that never sings. The passes are told + // apart by what the band does — the pluck thickening, the bells + // arriving, the floor thinning — and nothing else. + // + // ONE TAKE THROUGHOUT — @jeffrey: "stick with our original mapped + // take". f- is the one that was charted by hand, word by word, over a + // whole session; the others are warped onto ITS chart by singdub and + // are auditioned separately (bin/tryout-takes.sh) rather than dropped + // into the record. alt_line() is still here and still correct for + // when one of them earns a pass. + // + // L1 0–16 f- alone. Kick and one hat. + // L2 16–32 f- clap on 2 and 4; the bells arrive + // L3 32–48 f- the floor thins to the kick; the pads open + // L4 48–64 f- everything the band has + // L5 64–80 f- widest, bells running every bar + // L6 80–96 f- the ghost. thinning back to the pluck alone. - // ── V1 0–12 — THE UNBROKEN TAKE, first word ON beat 0 of bar 0 ───── - // One 12-bar continuous vocal; the pluck doubles her INSIDE the - // line — no answer gaps, the held vowels are the arrangement. - voice_line("w-whole-line", 0, 0.96, 0.18, 0, 0); - pluck_line("w-whole-line", 0, 0.5, 0, 0.3); - arp(at(4.5), ARP_III, 4, "oh", 5, 1, 0.15, 0.12, 0.35); // inside "stone…" - arp(at(8.5), ARP_VII, 3, "ah", 5, 0, 0.15, 0.12, -0.35); // inside "patiently…" + // THE DOWNBEAT still gets its bell, but it rings UNDER her first word + // now rather than in front of it — the record opens on a note and a + // voice at the same instant. + fembell(at(0), 0, 2.6, 0.26, 0.0); + fembell(at(0) + 0.012, 12, 2.2, 0.14, 0.28); + + // ── THE ROTA ───────────────────────────────────────────────────── + // Who says the hook, pass by pass. Handing one figure between + // instruments is what makes an arrangement read as structured rather + // than merely layered: the same four notes arrive in a different + // voice each time, so the ear tracks a thread instead of a texture. + // The statement lands on bar 1 of the pass; the ANSWER — the same + // figure inverted — lands on bar 5, and again on bar 13, so every + // pass is two four-bar sentences and a repeat. + // + // The turnaround closes each eight-bar row underneath all of it. + { + static const struct { int voice, oct; double gain; } SAYS[6] = { + { VOICE_PLUCK, 0, 0.30 }, // L1 the music box, alone + { VOICE_VIBE, 0, 0.34 }, // L2 the vibraphone takes it + { VOICE_BELL, 0, 0.24 }, // L3 bare section: bells only + { VOICE_VIBE, 12, 0.30 }, // L4 up an octave, the drop + { VOICE_PLUCK, 12, 0.28 }, // L5 widest — pluck and vibe + { VOICE_VIBE, 0, 0.22 }, // L6 the vibraphone, last + }; + for (int pass = 0; pass < 6; pass++) { + double b0 = L(pass); + double g = SAYS[pass].gain; + hook_say(at(b0 + 1), HOOK, SAYS[pass].oct, SAYS[pass].voice, g, 0.32); + hook_say(at(b0 + 5), HOOK_ANS, SAYS[pass].oct, SAYS[pass].voice, g * 0.9, -0.32); + hook_say(at(b0 + 13), HOOK_ANS, SAYS[pass].oct, SAYS[pass].voice, g * 0.8, 0.28); + if (pass == 4) // the widest pass says it in two voices + hook_say(at(b0 + 5) + 0.5 * BEAT, HOOK_ANS, 0, VOICE_VIBE, + g * 0.7, -0.36); + for (int row = 0; row < 2; row++) + turnaround(b0 + row * 8 + 7, pass == 2 ? 0.16 : 0.26); + } + } + + // ── L1 — alone ─────────────────────────────────────────────────── + // @jeffrey: "the vocal coming in should be softer". She was arriving + // at 0.96, the same level she holds for the rest of the record, which + // makes the first word an announcement. It is the softest take in the + // bank and the intro has just spent sixteen bars getting quiet for it; + // 0.62 lets her be heard rather than delivered, and the next pass is + // where she comes up to full. + voice_line("w-whole-line", L(0), 0.62); + pluck_line("w-whole-line", L(0), 0.44, 0, 0.3); + bell_run(at(L(0) + 6), &CH_VI, 3, 0.30, 0.13, 1, 0.35); + bell_run(at(L(0) + 13), &CH_VII, 3, 0.28, 0.12, 0, -0.35); + + // THE VIBRAPHONE answers her held notes. Every unit four beats or + // longer is a place where she stops moving, and the vibe fills it with + // a falling three-note figure off the bar's chord — so the new + // instrument is not another layer running in parallel, it plays in the + // gaps the singer leaves. + { + const ChartPhrase *pp = phrase_of("w-whole-line"); + for (int pass = 1; pass < 6; pass++) { + if (pass == 2) continue; // L3 stays bare + double base = L(pass); + double g = (pass == 1) ? 0.26 : (pass == 5) ? 0.20 : 0.34; + for (int i = 0; i < pp->n; i++) { + const ChartNote *nn = &pp->notes[i]; + if (nn->dur < 4.0) continue; + double t0 = at(base) + (nn->beat + nn->dur * 0.55) * BEAT; + const Chord *c = chord_at((int)(base + nn->beat / 4.0)); + for (int k = 0; k < 3; k++) + vibe(t0 + k * 0.5 * BEAT, c->tones[2 - k] + 12, + 1.2, g * (1.0 - 0.18 * k), (k % 2 ? 0.34 : -0.30)); + } + } + } + + // ── L2 16–32 — the clap, and her melody in octaves ──────────────── + voice_line("w-whole-line", L(1), 0.88); + pluck_line("w-whole-line", L(1), 0.52, 0, 0.3); + pluck_line("w-whole-line", L(1), 0.24, 12, -0.3); + for (int bar = L(1) + 2; bar < L(2); bar += 4) + bell_run(at(bar) + 2.5 * BEAT, chord_at(bar), 4, 0.26, 0.16, + (bar / 4) % 2 == 0, 0.4); + // THE STAB arrives with the clap, still muffled — the filter opens + // pass by pass, so one figure carries the whole build. + for (int bar = L(1) + 4; bar < L(2); bar++) { + const Chord *c = chord_at(bar); + double v[4] = { c->tones[0], c->tones[1], c->tones[2], c->sev }; + stab(at(bar) + sw(3) + lean(bar, 1.5), v, 4, 0.34, 0.26, 0.22, 0.30); + stab(at(bar) + sw(7) + lean(bar, 3.5), v, 4, 0.30, 0.22, 0.22, -0.30); + } - // ── HOOK 12–20 — her held STONE opens it; the stab waits till 14 ─── - { Shot o = shot_defaults(); o.gain = 0.32; o.side = 0.85; o.dly = 0.3; o.rvb = 0.6; - o.attack = 0.5; shot("stone-long-12", at(12), &o); } - pluck_line("w-of-a-stone", 12, 0.55, 0, 0.3); // the melody leads - voice_line("w-of-a-stone", 14, 1.0, 0.24, 0.30, 0); - { Shot o = shot_defaults(); o.gain = 0.5; o.pan = 0.3; o.dly = 0.2; o.rvb = 0.4; - shot("hk-of-a", at(14) - 0.05, &o); } - voice_line("w-of-a-stone", 16, 0.72, 0.18, 0, 0); // the echo stab - voice_line("w-of-a-stone", 18, 1.0, 0.26, 0.32, 1); // crowned, tiles to V2 - pluck_line("w-of-a-stone", 18, 0.6, 12, -0.3); - { Shot o = shot_defaults(); o.gain = 0.26; o.side = 0.9; o.dly = 0.32; o.rvb = 0.65; - o.attack = 0.5; shot("stone-long-5", at(19), &o); } - { Shot o = shot_defaults(); o.gain = 0.20; o.pan = 0.4; o.side = 0.8; o.rvb = 0.5; - o.attack = 0.6; shot("ens-o-2", at(15), &o); } - arp(at(13.5), ARP_I, 5, "oh", 6, 1, 0.13, 0.15, 0.35); - arp(at(15.5), ARP_VI, 4, "ah", 6, 0, 0.13, 0.15, -0.35); - arp(at(17.5), ARP_III, 4, "oh", 6, 1, 0.13, 0.15, 0.35); - arp(at(19.5), ARP_VII, 3, "ah", 7, 0, 0.13, 0.15, -0.35); + // ── L3 32–48 — the floor thins ─────────────────────────────────── + voice_line("w-whole-line", L(2), 0.98); + pluck_line("w-whole-line", L(2), 0.40, 0, 0.3); + for (int bar = L(2) + 1; bar < L(2) + 14; bar += 3) + fembell(at(bar), chord_at(bar)->root, 2.2, 0.22, (bar % 6) ? 0.3 : -0.3); - // ── V2 20–28 — the "not again!" verse at HER pace, seamless ──────── - // (10.5 + 16.5 + 6 beats back-to-back: she sings straight through) - voice_line("w-n-getting-curled", 20, 0.92, 0.20, 0.26, 0); - pluck_line("w-n-getting-curled", 20, 0.5, 0, 0.3); - voice_line("w-n-stone-waiting", 22.625, 0.92, 0.20, 0.26, 0); - pluck_line("w-n-stone-waiting", 22.625, 0.5, 0, -0.3); - voice_line("w-n-for-time-to-pass", 26.5, 0.94, 0.22, 0.28, 1); - pluck_line("w-n-for-time-to-pass", 26.5, 0.55, 0, 0.3); - arp(at(26.5), ARP_IV, 3, "oh", 6, 1, 0.13, 0.14, 0.35); - arp(at(27.2), ARP_VII, 3, "ah", 7, 1, 0.12, 0.16, -0.35); + // ── THE DROP ───────────────────────────────────────────────────── + // @jeffrey: "and more epic drop". Four bars of preparation instead of + // none: the riser runs the whole way, the scratches answer each other + // across the stereo, and in the last bar the tape STOPS — screw_down + // drags "stone" from full speed to a third of it, so the pitch sags + // out from under the room. Then the floor returns at tempo, and a bell + // is struck on the downbeat itself so the drop arrives on a note and + // not only on a kick. + riser(at(L(3) - 4), 4 * BAR, 0.20); + scratch("w-whole-line", "pa", at(L(3) - 4) + 2 * BEAT, 4, 0.34, 0.40); + scratch("w-whole-line", "pass", at(L(3) - 3) + 2 * BEAT, 5, 0.36, -0.40); + scratch("w-whole-line", "pa", at(L(3) - 2) + 1 * BEAT, 6, 0.40, 0.42); + screw_down("w-whole-line", "stone", at(L(3) - 1), 1.5 * BAR, 0.62); + fembell(at(L(3)), 0, 3.4, 0.62, 0); + fembell(at(L(3)) + 0.012, 12, 3.4, 0.34, 0.25); + // the floor already puts a kick on this downbeat; these are the three + // 16ths AFTER it, so the drop stutters in rather than doubling a hit + for (int b = 1; b < 4; b++) + kick(at(L(3)) + b * (BEAT / 4.0), 0.54 - 0.12 * b); + + // ── L4 48–64 — everything the band has ─────────────────────────── + voice_line("w-whole-line", L(3), 0.98); + pluck_line("w-whole-line", L(3), 0.55, 0, 0.3); + pluck_line("w-whole-line", L(3), 0.28, 12, -0.3); + for (int bar = L(3); bar < L(4); bar += 2) + bell_run(at(bar) + 1.0 * BEAT, chord_at(bar), 5, 0.24, 0.20, + (bar / 2) % 2, (bar % 4) ? 0.42 : -0.42); + for (int bar = L(3); bar < L(4); bar++) { + // THE STAB RESTS WHERE THE HOOK SPEAKS. Two ideas on the offbeat + // at once is not counterpoint, it is a pile; the arrangement reads + // as deliberate the moment something stops to let something else + // through. + int said = (bar == L(3) + 1 || bar == L(3) + 5 || bar == L(3) + 13); + if (said) continue; + const Chord *c = chord_at(bar); + double v[4] = { c->tones[0], c->tones[1], c->tones[2], c->sev }; + stab(at(bar) + sw(3) + lean(bar, 1.5), v, 4, 0.36, 0.34, 0.58, 0.32); + stab(at(bar) + sw(7) + lean(bar, 3.5), v, 4, 0.32, 0.30, 0.58, -0.32); + if (bar % 4 == 3) + stab(at(bar) + sw(5.5) + lean(bar, 2.75), v, 4, 0.18, 0.24, 0.72, 0.0); + } + // PA — announced, then answered. @jeffrey: "can 'patiently' especially + // 'pa' be cooler". The stutter runs three 16ths into it so the scoop is + // heard coming; the throw is the same word an octave later, off the + // beat, gone into the delay. + word_stutter("w-whole-line", "pa", L(3), 0.40, 0.34); + word_throw("w-whole-line", "pa", L(3), 0.52, 0.75 * BEAT, -0.36); - // ── BREAK 28–40 — the whole take again, naked over pads ──────────── - voice_line("w-whole-line", 28, 1.0, 0.15, 0, 0); - { Shot o = shot_defaults(); o.gain = 0.22; o.side = 0.9; o.dly = 0.3; o.rvb = 0.7; - o.attack = 0.8; shot("stone-long-echo", at(33), &o); } - dust(at(30) + 1.1, 0.013); dust(at(35) + 2.3, 0.015); - arp(at(36.5), ARP_I, 5, "oh", 4, 1, 0.28, 0.09, 0.3); + // …and the door the last pass comes through + riser(at(L(4) - 3), 3 * BAR, 0.17); + scratch("w-whole-line", "think", at(L(4) - 2) + 2 * BEAT, 5, 0.32, -0.38); + screw_down("w-whole-line", "pa", at(L(4) - 1) + 2 * BEAT, 0.9 * BAR, 0.52); + fembell(at(L(4)), -4, 3.2, 0.46, -0.2); - // ── DROP 40–58 — the unbroken take with everything she has ───────── - voice_line("w-whole-line", 40, 0.98, 0.24, 0.32, 1); - pluck_line("w-whole-line", 40, 0.55, 0, 0.3); - { Shot o = shot_defaults(); o.gain = 0.5; o.pan = -0.3; o.dly = 0.2; o.rvb = 0.4; - shot("hk-of-a", at(43.25) - 0.05, &o); } // under "of a" - { Shot o = shot_defaults(); o.gain = 0.24; o.side = 0.85; o.dly = 0.3; o.rvb = 0.6; - o.attack = 0.5; shot("pass-long-15", at(49.6), &o); } - voice_line("w-of-a-stone", 52, 1.0, 0.26, 0.34, 1); - pluck_line("w-of-a-stone", 52, 0.6, 12, 0.35); - { Shot o = shot_defaults(); o.gain = 0.30; o.side = 0.9; o.dly = 0.34; o.rvb = 0.7; - o.attack = 0.5; shot("stone-long-17", at(53), &o); } - { Shot o = shot_defaults(); o.gain = 0.22; o.pan = -0.4; o.side = 0.85; o.rvb = 0.55; - o.attack = 0.7; shot("ens-du-2", at(53), &o); } - voice_line("w-of-a-stone", 54, 0.78, 0.20, 0, 0); - voice_line("w-for-time-to-pass", 56, 0.92, 0.22, 0.28, 0); // flows into the OUT - for (int bar = 40; bar < 58; bar += 2) { - const int *tones = (bar % 8 < 2) ? ARP_I : (bar % 8 < 4) ? ARP_VI : - (bar % 8 < 6) ? ARP_III : ARP_VII; - int nt = (tones == ARP_III) ? 4 : (tones == ARP_VII) ? 3 : - (tones == ARP_I) ? 5 : 4; - arp(at(bar) + 0.5 * BAR, tones, nt, (bar % 4) ? "ah" : "oh", - 7, (bar / 2) % 2 == 0, 0.12, 0.16, 0.35); + // ── L5 64–80 — widest ──────────────────────────────────────────── + voice_line("w-whole-line", L(4), 0.98); + pluck_line("w-whole-line", L(4), 0.52, 0, 0.3); + pluck_line("w-whole-line", L(4), 0.30, 12, -0.3); + pluck_line("w-whole-line", L(4), 0.18, -12, 0.15); + for (int bar = L(4); bar < L(5); bar += 2) + bell_run(at(bar) + 1.0 * BEAT, chord_at(bar), 5, 0.22, 0.22, + (bar / 2) % 2, (bar % 4) ? 0.44 : -0.44); + for (int bar = L(4); bar < L(5); bar++) { + int said = (bar == L(4) + 1 || bar == L(4) + 5 || bar == L(4) + 13); + if (said) continue; + const Chord *c = chord_at(bar); + double v[4] = { c->tones[0], c->tones[1], c->tones[2], c->sev }; + stab(at(bar) + sw(3) + lean(bar, 1.5), v, 4, 0.36, 0.36, 0.86, 0.34); + stab(at(bar) + sw(7) + lean(bar, 3.5), v, 4, 0.32, 0.32, 0.86, -0.34); + if (bar % 2 == 1) + stab(at(bar) + sw(5.5) + lean(bar, 2.75), v, 4, 0.18, 0.26, 0.95, 0.0); } + word_stutter("w-whole-line", "pa", L(4), 0.46, 0.36); + word_throw("w-whole-line", "pa", L(4), 0.58, 0.75 * BEAT, 0.38); + word_throw("w-whole-line", "pa", L(4), 0.30, 2.25 * BEAT, -0.42); - // ── OUT 58–76 — the ghost: the whole take once more, far away, - // under the pluck singing the same line ──────────────────────────── - voice_line("w-whole-line", 58, 0.55, 0.16, 0, 0); - pluck_line("w-whole-line", 58, 0.5, 0, 0.3); - pluck_line("w-for-time-to-pass", 70, 0.36, 12, 0.35); - { Shot o = shot_defaults(); o.gain = 0.18; o.side = 0.9; o.dly = 0.3; o.rvb = 0.75; - o.attack = 0.8; shot("pass-long-3", at(72), &o); } - { Shot o = shot_defaults(); o.gain = 0.14; o.pan = 0.3; o.side = 0.8; o.rvb = 0.6; - o.attack = 0.9; shot("ens-o-3", at(70), &o); } - arp(at(73), ARP_I, 5, "oh", 4, 0, 0.28, 0.09, 0.3); - arp(at(74.5), ARP_I, 5, "ah", 3, 0, 0.30, 0.07, -0.3); - dust(at(59) + 0.4, 0.012); dust(at(69) + 2.1, 0.014); dust(at(74) + 1.2, 0.013); - hiss_bed(); + // ── L6 80–96 — the ghost. she is the last one left ─────────────── + voice_line("w-whole-line", L(5), 0.72); + pluck_line("w-whole-line", L(5), 0.50, 0, 0.3); + pluck_line("w-whole-line", L(5), 0.20, 12, -0.3); + bell_run(at(L(5) + 2), &CH_i, 4, 0.30, 0.16, 0, 0.35); + bell_run(at(L(5) + 6), &CH_VI, 3, 0.32, 0.12, 0, -0.35); + fembell(at(L(5) + 10), 0, 3.0, 0.12, 0.2); mixdown: if (missingN) fprintf(stderr, " ! %d missing samples\n", missingN); @@ -858,8 +1622,88 @@ // "side chained into the lyrics": every kick ducks the vox 0.34 and // the bed 0.52; drums never duck. // harsher sidechain — deeper on both buses and a faster grab, so // the pump is something you feel rather than infer - float *envBed = duck_env(0.68, 0.008, 0.26); - float *envVox = duck_env(0.52, 0.008, 0.22); + // The STUDY's kick lands on all four, so the dance mix's 0.68 duck + // holds the bed down almost continuously and the pads never surface + // — @jeffrey: "also the pads arent sounding". A monitor wants to hear + // what it is judging; the dance depth stays on the real cut. + // @jeffrey: "and side chainnig!" — it was already here, doing its job + // quietly. The point of asking for it out loud is that you want to + // HEAR it, and what makes a pump audible is not depth, it is the + // RELEASE: a duck that recovers in 260 ms is most of the way back + // before the next kick and reads as a level change. Shortening it to + // 190 ms and grabbing faster makes the bed breathe in and out between + // every beat, which is the sound. Depth up a little too, but the + // release is what you notice. + float *envBed = duck_env(minimal ? 0.28 : 0.76, 0.005, 0.19); + // …and the duck on the voice comes back to the 0.34 the comment above + // always claimed. 0.52 is six dB of movement on the lead four times a + // bar, which reads as pumping rather than as a floor once the 16ths + // are gone and there is nothing else covering it. + float *envVox = duck_env(0.38, 0.006, 0.20); + // SOLO=music (or drums / vox, comma-separated) mutes the rest — + // @jeffrey: "im not hearing those instruments · are they toggled + // off?". A bus you cannot solo can only be argued about; this makes + // the question answerable in one render. + const char *soloEnv = getenv("SOLO"); + double gD = 1, gM = 1, gV = 1; + if (soloEnv && *soloEnv) { + gD = strstr(soloEnv, "drums") ? 1 : 0; + gM = strstr(soloEnv, "music") ? 1 : 0; + gV = strstr(soloEnv, "vox") ? 1 : 0; + printf(" SOLO=%s — drums %.0f · music %.0f · vox %.0f\n", soloEnv, gD, gM, gV); + } + // ── THE VOCAL CHAIN — @jeffrey: "we need to master / treat each + // vocal separate right?". Right. Until now the vox bus got a static + // gain and a sidechain duck and nothing else, and her line swings 23 + // dB across one sentence — "sitting" peaks at −6, "waiting" sits at + // −29. A single fader cannot serve both: set it for the loud words + // and the quiet ones fall under the floor; set it for the quiet ones + // and she shouts. So the lead gets its own compressor, linked across + // the pair so the image does not wander, ahead of the mix and ahead + // of the master. + { + const double th = 0.10; // ≈ −20 dBFS on this bus + const double ratio = 3.0, mk = 2.1; + const double aA = 1 - exp(-1.0 / (0.012 * SR)); // 12 ms + const double aR = 1 - exp(-1.0 / (0.140 * SR)); // 140 ms + // …and a scoop where PROXIMITY lives. A voice close to a mic is + // thick between about 150 and 800 Hz; taking some of that out is + // what makes it read as further away, and unlike a lowpass it + // leaves the sibilant restore alone — the /s/ that took all day to + // find stays exactly as loud as it was. + const double kLo = 1 - exp((-TAU * 150.0) / SR); + const double kHi = 1 - exp((-TAU * 800.0) / SR); + // …further back again — @jeffrey, twice now: "i think the voice + // should be deeper in the [m]ix". Each of the three levers moves + // together, because only moving the fader makes a quiet close + // voice rather than a distant one: 1.02 → 0.82 direct, 0.46 → 0.58 + // room, and the proximity scoop from a third to nearly half. + const double chest = 0.44; + double lo[2] = {0, 0}, hi[2] = {0, 0}; + double env = 0, gr = 1, worst = 1; + for (long i = 0; i < N; i++) { + double d = fmax(fabs((double)voxL[i]), fabs((double)voxR[i])); + env += (d > env ? aA : aR) * (d - env); + double want = env > th ? (th + (env - th) / ratio) / env : 1.0; + gr += (want < gr ? aA : aR) * (want - gr); + if (gr < worst) worst = gr; + double l = voxL[i] * gr * mk, r = voxR[i] * gr * mk; + lo[0] += kLo * (l - lo[0]); hi[0] += kHi * (l - hi[0]); + lo[1] += kLo * (r - lo[1]); hi[1] += kHi * (r - hi[1]); + voxL[i] = (float)(l - chest * (hi[0] - lo[0])); + voxR[i] = (float)(r - chest * (hi[1] - lo[1])); + } + printf(" vox comp — max %.1f dB down\n", 20 * log10(worst)); + } + { // bus peaks, so a silent bus is visible rather than argued about + double pd = 0, pm = 0, pv = 0; + for (long i = 0; i < N; i++) { + pd = fmax(pd, fabs((double)drumsL[i])); + pm = fmax(pm, fabs((double)musicL[i])); + pv = fmax(pv, fabs((double)voxL[i])); + } + printf(" bus peaks — drums %.3f · music %.3f · vox %.3f\n", pd, pm, pv); + } float *L = calloc(N, 4), *R = calloc(N, 4); // band-limited antisymmetric side (one-pole at 6 kHz) double kSide = 1 - exp((-TAU * 6000) / SR); @@ -868,8 +1712,8 @@ for (long i = 0; i < N; i++) { sV += kSide * (sideV[i] - sV); sB += kSide * (sideB[i] - sB); double bed = envBed[i], vx = envVox[i] * VOXG; - double l = drumsL[i] + (musicL[i] + sB) * bed + (voxL[i] + sV) * vx; - double r = drumsR[i] + (musicR[i] - sB) * bed + (voxR[i] - sV) * vx; + double l = drumsL[i] * gD + (musicL[i] + sB) * bed * gM + (voxL[i] + sV) * vx * gV; + double r = drumsR[i] * gD + (musicR[i] - sB) * bed * gM + (voxR[i] - sV) * vx * gV; L[i] = (float)l; R[i] = (float)r; } double peak = 0; diff --git a/pop/loner/covers/club-floor.illy.txt b/pop/loner/covers/club-floor.illy.txt new file mode 100644 --- /dev/null +++ b/pop/loner/covers/club-floor.illy.txt @@ -0,0 +1,31 @@ +a photograph of a colored-pencil and gouache drawing on deep indigo paper. +square, 1:1. seen from directly overhead, straight down, flat plan view. + +a dancefloor with thirty people on it, and every one of them is alone. + +each person is the same figure from the reference score, drawn here as one +continuous white chalk line on the dark floor: sitting curled up, knees to the +chest, arms wrapped round the shins, head down on the knees, long thin lines +trailing past the feet. wobbling, un-erased, one unbroken stroke each, overlaps +visible. they are laid out on the score's own grid — six rows of five, evenly +spaced, none of them touching, none of them turned toward another. + +light is diegetic and comes from the floor: one small coloured lamp set into +the boards beside each figure — magenta, cyan, chartreuse, amber, violet, +mixed through the grid — each throwing a pool that reaches to the edge of its +own person and stops. thirty little islands of light. the floor between them +stays dark indigo, and the chalk lines outside a pool read only as faint grey. +the boards are visible in the pools: plain worn wood, no pattern, no logo. + +chalked on the floor beside six of the figures — one word each, small, +lowercase, in the same hand as the drawing: + + sitting · assise · sentada · sidder · сижу · बैठी + +six languages, one posture, nobody talking to anybody. that is the club. + +NO motion blur, NO soft-focus haze, NO lens flare, NO overlay glow — the light +is drawn, and the chalk stays crisp. NO title lettering, NO artist name, NO +band or label logo, NO barcode, NO url, NO @handle, NO brand signage, NO +flags, NO emblems, NO dj booth, NO speakers, NO disco ball. those six words +are the only text in the picture. diff --git a/pop/loner/covers/lonerclub-cover-a-score-international.png b/pop/loner/covers/lonerclub-cover-a-score-international.png new file mode 100644 --- /dev/null +++ b/pop/loner/covers/lonerclub-cover-a-score-international.png diff --git a/pop/loner/covers/lonerclub-cover-a-score-international.png.illy.json b/pop/loner/covers/lonerclub-cover-a-score-international.png.illy.json new file mode 100644 --- /dev/null +++ b/pop/loner/covers/lonerclub-cover-a-score-international.png.illy.json @@ -0,0 +1,44 @@ +{ + "schema": "illy/v1", + "createdAt": "2026-08-19T16:18:42.896Z", + "pipeline": "pop-cover", + "provider": "openai", + "model": "gpt-image-2", + "mode": "edit", + "size": "1024x1024", + "quality": "high", + "output": "/Users/jas/aesthetic-computer/pop/loner/covers/lonerclub-cover-a-score-international.png", + "promptPath": "/Users/jas/aesthetic-computer/pop/loner/covers/score-international.illy.txt", + "promptHash": "b0cf687caa36be591ba1a032ca135d18fcaf1dbc459f6cff0174211d6dd5b747", + "references": [ + "/Users/jas/aesthetic-computer/pop/loner/covers/refs/loner-score-small.png", + "/Users/jas/aesthetic-computer/pop/loner/covers/refs/loner-curl-row.png" + ], + "contracts": [ + "physical-accuracy" + ], + "stages": [ + "resolve-inputs", + "apply-contracts", + "select-provider", + "generate", + "archive", + "provenance" + ], + "durationSeconds": 138.86, + "archived": null, + "requestId": null, + "usage": { + "input_tokens": 2824, + "input_tokens_details": { + "image_tokens": 2156, + "text_tokens": 668 + }, + "output_tokens": 7024, + "output_tokens_details": { + "image_tokens": 7024, + "text_tokens": 0 + }, + "total_tokens": 9848 + } +} diff --git a/pop/loner/covers/lonerclub-cover-b-stone.png b/pop/loner/covers/lonerclub-cover-b-stone.png new file mode 100644 --- /dev/null +++ b/pop/loner/covers/lonerclub-cover-b-stone.png diff --git a/pop/loner/covers/lonerclub-cover-b-stone.png.illy.json b/pop/loner/covers/lonerclub-cover-b-stone.png.illy.json new file mode 100644 --- /dev/null +++ b/pop/loner/covers/lonerclub-cover-b-stone.png.illy.json @@ -0,0 +1,43 @@ +{ + "schema": "illy/v1", + "createdAt": "2026-08-19T16:20:54.630Z", + "pipeline": "pop-cover", + "provider": "openai", + "model": "gpt-image-2", + "mode": "edit", + "size": "1024x1024", + "quality": "high", + "output": "/Users/jas/aesthetic-computer/pop/loner/covers/lonerclub-cover-b-stone.png", + "promptPath": "/Users/jas/aesthetic-computer/pop/loner/covers/stone.illy.txt", + "promptHash": "6518f5a93c9032240f38d4483b6656b5b25e575b6c6ae996c09e64bc6bb95f95", + "references": [ + "/Users/jas/aesthetic-computer/pop/loner/covers/refs/loner-curl-row.png" + ], + "contracts": [ + "physical-accuracy" + ], + "stages": [ + "resolve-inputs", + "apply-contracts", + "select-provider", + "generate", + "archive", + "provenance" + ], + "durationSeconds": 129.524, + "archived": null, + "requestId": null, + "usage": { + "input_tokens": 1297, + "input_tokens_details": { + "image_tokens": 660, + "text_tokens": 637 + }, + "output_tokens": 7024, + "output_tokens_details": { + "image_tokens": 7024, + "text_tokens": 0 + }, + "total_tokens": 8321 + } +} diff --git a/pop/loner/covers/lonerclub-cover-c-club-floor.png b/pop/loner/covers/lonerclub-cover-c-club-floor.png new file mode 100644 --- /dev/null +++ b/pop/loner/covers/lonerclub-cover-c-club-floor.png diff --git a/pop/loner/covers/lonerclub-cover-c-club-floor.png.illy.json b/pop/loner/covers/lonerclub-cover-c-club-floor.png.illy.json new file mode 100644 --- /dev/null +++ b/pop/loner/covers/lonerclub-cover-c-club-floor.png.illy.json @@ -0,0 +1,44 @@ +{ + "schema": "illy/v1", + "createdAt": "2026-08-19T16:28:06.947Z", + "pipeline": "pop-cover", + "provider": "openai", + "model": "gpt-image-2", + "mode": "edit", + "size": "1024x1024", + "quality": "high", + "output": "/Users/jas/aesthetic-computer/pop/loner/covers/lonerclub-cover-c-club-floor.png", + "promptPath": "/Users/jas/aesthetic-computer/pop/loner/covers/club-floor.illy.txt", + "promptHash": "59e9cc2d66cb07f0e1cdfbeaa5da8e321e99a1a24260a3b1c7d5bf0b6f1bb6e8", + "references": [ + "/Users/jas/aesthetic-computer/pop/loner/covers/refs/loner-curl-row.png", + "/Users/jas/aesthetic-computer/pop/loner/covers/refs/loner-score-small.png" + ], + "contracts": [ + "physical-accuracy" + ], + "stages": [ + "resolve-inputs", + "apply-contracts", + "select-provider", + "generate", + "archive", + "provenance" + ], + "durationSeconds": 162.591, + "archived": null, + "requestId": null, + "usage": { + "input_tokens": 2816, + "input_tokens_details": { + "image_tokens": 2156, + "text_tokens": 660 + }, + "output_tokens": 7024, + "output_tokens_details": { + "image_tokens": 7024, + "text_tokens": 0 + }, + "total_tokens": 9840 + } +} diff --git a/pop/loner/covers/refs/loner-curl-row.png b/pop/loner/covers/refs/loner-curl-row.png new file mode 100644 --- /dev/null +++ b/pop/loner/covers/refs/loner-curl-row.png diff --git a/pop/loner/covers/refs/loner-score-small.png b/pop/loner/covers/refs/loner-score-small.png new file mode 100644 --- /dev/null +++ b/pop/loner/covers/refs/loner-score-small.png diff --git a/pop/loner/covers/refs/loner-score.png b/pop/loner/covers/refs/loner-score.png new file mode 100644 --- /dev/null +++ b/pop/loner/covers/refs/loner-score.png diff --git a/pop/loner/covers/score-international.illy.txt b/pop/loner/covers/score-international.illy.txt new file mode 100644 --- /dev/null +++ b/pop/loner/covers/score-international.illy.txt @@ -0,0 +1,36 @@ +a photograph of a hand-drawn graphic score on white paper. square, 1:1. + +the reference image is the score this is made from — copy its line exactly. +one figure, drawn in ONE continuous grey marker stroke, curling from standing +to a ball: upright, then a bend at the waist, then the knees rise, then the +arms wrap the shins, then the head goes down onto the knees and long thin +lines trail past the feet. wobbling, un-erased, mid-grey, every overlap left +visible. no shading, no fill, no outline weight changes — just the one line. + +six rows. five figures per row. the same curl runs left to right in every row, +so the whole page is one person sitting down thirty times. even spacing, +generous white margin on all four sides, no border, no frame, no box. + +what changes row to row is the handwriting underneath. under each row, ONE +word, small, lowercase, hand-lettered in soft pencil in the same hand as the +drawing: + + row 1 — sitting + row 2 — assise + row 3 — sentada + row 4 — sidder + row 5 — сижу + row 6 — बैठी + +one word per row, centred under the row, nothing else. the drawing is the +language everybody already reads — the words are just the annotation. + +the remix lives in the colour. five of the thirty figures are drawn in +saturated marker instead of grey — magenta, cyan, chartreuse, orange, violet — +one per row, stepping diagonally down the page from top-left to bottom-right, +so a pulse walks through the sentence. every other figure stays grey. + +NO title lettering, NO artist name, NO band or label logo, NO barcode, NO url, +NO @handle, NO brand signage, NO flags, NO country names, NO emblems. the six +words above are the only text in the picture. the drawing dissolves to plain +white paper at the edges. diff --git a/pop/loner/covers/stone.illy.txt b/pop/loner/covers/stone.illy.txt new file mode 100644 --- /dev/null +++ b/pop/loner/covers/stone.illy.txt @@ -0,0 +1,32 @@ +a photograph of a colored-pencil and gouache drawing on pure white paper. +square, 1:1. + +one stone. grey, palm-sized, ordinary — the kind you pick up and keep for no +reason. it sits alone in the middle of the page with one soft hatched shadow +under it. built from confident hatching and striping, tapered pencil edges, +visible paper grain, tertiary greys made by overlaying strokes rather than +blending. no floor, no horizon, no room — the stone floats on the white with a +generous margin on all four sides. + +drawn ON the stone, following the curve of the rock like a petroglyph: a person +sitting curled up — knees to the chest, arms round the shins, head down, long +thin lines trailing past the feet — in ONE continuous grey marker stroke, +wobbling and un-erased, exactly the hand in the reference score. the line lies +on the surface and bends where the surface bends, dimming slightly where the +stone turns away from the light. it is not floating in front of the stone. + +around the base, following the stone's silhouette like a tide line, one word +written six times in small pencil handwriting, one per script, evenly spaced, +lowercase where the script has a lowercase: + + stone · pierre · piedra · sten · камень · पत्थर + +the same thing, named six ways, waiting. + +light is one soft daylight source from the upper left. NO glow overlay, NO +motion blur, NO soft-focus haze — the pencil is crisp from front to back. + +NO title lettering, NO artist name, NO band or label logo, NO barcode, NO url, +NO @handle, NO brand signage, NO flags, NO emblems. those six words are the +only text in the picture. the drawing dissolves to plain white paper at the +edges — no border, no frame. diff --git a/pop/loner/samples/.align.json b/pop/loner/samples/.align.json --- a/pop/loner/samples/.align.json +++ b/pop/loner/samples/.align.json @@ -5,127 +5,127 @@ "text": "sitting curled up in myself i think of a stone, just waiting very patiently for time to pass", "words": [ { "t": "sitting", - "start": 0.0, - "end": 1.4, + "start": 0.22, + "end": 1.62, "f0_hz": 348.8, "note": "F4" }, { "t": "curled", - "start": 1.4, - "end": 2.44, + "start": 1.62, + "end": 2.66, "f0_hz": 278.2, "note": "C#4" }, { "t": "up", - "start": 2.44, - "end": 3.14, + "start": 2.66, + "end": 3.36, "f0_hz": 265.3, "note": "C4" }, { "t": "in", - "start": 3.14, - "end": 3.94, + "start": 3.36, + "end": 4.16, "f0_hz": 237.3, "note": "A#3" }, { "t": "myself", - "start": 3.94, - "end": 5.32, + "start": 4.16, + "end": 5.54, "f0_hz": 309.4, "note": "D#4" }, { "t": "i", - "start": 5.32, - "end": 6.26, + "start": 5.54, + "end": 6.48, "f0_hz": 211.0, "note": "G#3" }, { "t": "think", - "start": 6.26, - "end": 6.86, + "start": 6.48, + "end": 7.08, "f0_hz": 175.6, "note": "F3" }, { "t": "of", - "start": 6.86, - "end": 8.8, + "start": 7.08, + "end": 9.02, "f0_hz": 470.6, "note": "A#4" }, { "t": "a", - "start": 8.8, - "end": 9.6, + "start": 9.02, + "end": 9.82, "f0_hz": 429.4, "note": "G#4" }, { "t": "stone", - "start": 9.6, - "end": 10.48, + "start": 9.82, + "end": 10.7, "f0_hz": 317.4, "note": "D#4" }, { "t": "just", - "start": 11.115, - "end": 12.38, + "start": 11.335, + "end": 12.6, "f0_hz": 268.1, "note": "C4" }, { "t": "waiting", - "start": 12.38, - "end": 14.04, + "start": 12.6, + "end": 14.26, "f0_hz": 279.9, "note": "C#4" }, { "t": "very", - "start": 14.04, - "end": 15.96, + "start": 14.26, + "end": 16.18, "f0_hz": 237.3, "note": "A#3" }, { "t": "patiently", - "start": 15.96, - "end": 17.26, + "start": 16.18, + "end": 17.48, "f0_hz": 357.2, "note": "F4" }, { "t": "for", - "start": 17.26, - "end": 19.16, + "start": 17.48, + "end": 19.38, "f0_hz": 283.8, "note": "C#4" }, { "t": "time", - "start": 19.16, - "end": 20.5, + "start": 19.38, + "end": 20.72, "f0_hz": 357.5, "note": "F4" }, { "t": "to", - "start": 20.5, - "end": 22.64, + "start": 20.72, + "end": 22.86, "f0_hz": 282.4, "note": "C#4" }, { "t": "pass", - "start": 22.64, - "end": 24.2, + "start": 22.86, + "end": 24.42, "f0_hz": 282.0, "note": "C#4" } diff --git a/pop/loner/samples/.manifest.json b/pop/loner/samples/.manifest.json --- a/pop/loner/samples/.manifest.json +++ b/pop/loner/samples/.manifest.json @@ -19,35 +19,35 @@ "t": "cur", "start": 1.74, "end": 2.48, "f0_hz": 278, - "note": "C♯4" + "note": "C\u266f4" }, { "t": "led", "start": 2.48, "end": 3.47, "f0_hz": 271.6, - "note": "C♯4" + "note": "C\u266f4" }, { "t": "up", "start": 3.47, "end": 3.72, "f0_hz": 236.5, - "note": "A♯3" + "note": "A\u266f3" }, { "t": "in", "start": 3.72, "end": 4.22, "f0_hz": 237.8, - "note": "A♯3" + "note": "A\u266f3" }, { "t": "myself", "start": 4.22, "end": 5.76, "f0_hz": 317.5, - "note": "D♯4" + "note": "D\u266f4" } ] }, @@ -64,14 +64,14 @@ "t": "I", "start": 5.76, "end": 5.96, "f0_hz": 209.5, - "note": "G♯3" + "note": "G\u266f3" }, { "t": "think", "start": 5.96, "end": 7.46, "f0_hz": 210.7, - "note": "G♯3" + "note": "G\u266f3" } ] }, @@ -88,14 +88,14 @@ "t": "of", "start": 7.46, "end": 8.06, "f0_hz": 470.2, - "note": "A♯4" + "note": "A\u266f4" }, { "t": "a", "start": 8.06, "end": 8.59, "f0_hz": 472.9, - "note": "A♯4" + "note": "A\u266f4" }, { "t": "stone", @@ -119,28 +119,28 @@ "t": "I", "start": 5.76, "end": 5.96, "f0_hz": 209.5, - "note": "G♯3" + "note": "G\u266f3" }, { "t": "think", "start": 5.96, "end": 7.46, "f0_hz": 210.7, - "note": "G♯3" + "note": "G\u266f3" }, { "t": "of", "start": 7.46, "end": 8.06, "f0_hz": 470.2, - "note": "A♯4" + "note": "A\u266f4" }, { "t": "a", "start": 8.06, "end": 8.59, "f0_hz": 472.9, - "note": "A♯4" + "note": "A\u266f4" }, { "t": "stone", @@ -188,21 +188,21 @@ "t": "waiting", "start": 13.01, "end": 14.71, "f0_hz": 279.6, - "note": "C♯4" + "note": "C\u266f4" }, { "t": "very", "start": 14.71, "end": 16.29, "f0_hz": 236.5, - "note": "A♯3" + "note": "A\u266f3" }, { "t": "patiently", "start": 16.29, "end": 18.82, "f0_hz": 317.5, - "note": "D♯4" + "note": "D\u266f4" } ] }, @@ -226,7 +226,7 @@ "t": "waiting", "start": 13.01, "end": 14.71, "f0_hz": 279.6, - "note": "C♯4" + "note": "C\u266f4" } ] }, @@ -243,14 +243,14 @@ "t": "very", "start": 14.71, "end": 16.29, "f0_hz": 236.5, - "note": "A♯3" + "note": "A\u266f3" }, { "t": "patiently", "start": 16.29, "end": 18.82, "f0_hz": 317.5, - "note": "D♯4" + "note": "D\u266f4" } ] }, @@ -267,7 +267,7 @@ "t": "for", "start": 18.82, "end": 19.78, "f0_hz": 319.3, - "note": "D♯4" + "note": "D\u266f4" }, { "t": "time", @@ -281,14 +281,14 @@ "t": "to", "start": 21.4, "end": 23.12, "f0_hz": 282.8, - "note": "C♯4" + "note": "C\u266f4" }, { "t": "pass", "start": 23.12, "end": 24.99, "f0_hz": 282.8, - "note": "C♯4" + "note": "C\u266f4" } ] }, @@ -305,150 +305,150 @@ "t": "pass", "start": 23.12, "end": 24.99, "f0_hz": 282.8, - "note": "C♯4" + "note": "C\u266f4" } ] }, "f-whole-line": { "source": "7108062006980201771", - "start": 0.28, + "start": 0.06, "end": 25.45, "words": "the whole lyric, one take", - "dur": 24.307, + "dur": 24.527, "median_f0_hz": 282.8, "word_f0": [ { "t": "Sitting", - "start": 0.33, - "end": 1.74, + "start": 0.55, + "end": 1.96, "f0_hz": 348.2, "note": "F4" }, { "t": "cur", - "start": 1.74, - "end": 2.48, + "start": 1.96, + "end": 2.7, "f0_hz": 278, - "note": "C♯4" + "note": "C\u266f4" }, { "t": "led", - "start": 2.48, - "end": 3.47, + "start": 2.7, + "end": 3.69, "f0_hz": 271.6, - "note": "C♯4" + "note": "C\u266f4" }, { "t": "up", - "start": 3.47, - "end": 3.72, + "start": 3.69, + "end": 3.94, "f0_hz": 236.5, - "note": "A♯3" + "note": "A\u266f3" }, { "t": "in", - "start": 3.72, - "end": 4.22, + "start": 3.94, + "end": 4.44, "f0_hz": 237.8, - "note": "A♯3" + "note": "A\u266f3" }, { "t": "myself", - "start": 4.22, - "end": 5.76, + "start": 4.44, + "end": 5.98, "f0_hz": 317.5, - "note": "D♯4" + "note": "D\u266f4" }, { "t": "I", - "start": 5.76, - "end": 5.96, + "start": 5.98, + "end": 6.18, "f0_hz": 209.5, - "note": "G♯3" + "note": "G\u266f3" }, { "t": "think", - "start": 5.96, - "end": 7.46, + "start": 6.18, + "end": 7.68, "f0_hz": 210.7, - "note": "G♯3" + "note": "G\u266f3" }, { "t": "of", - "start": 7.46, - "end": 8.06, + "start": 7.68, + "end": 8.28, "f0_hz": 470.2, - "note": "A♯4" + "note": "A\u266f4" }, { "t": "a", - "start": 8.06, - "end": 8.59, + "start": 8.28, + "end": 8.81, "f0_hz": 472.9, - "note": "A♯4" + "note": "A\u266f4" }, { "t": "stone", - "start": 8.59, - "end": 11.29, + "start": 8.81, + "end": 11.51, "f0_hz": 325.8, "note": "E4" }, { "t": "just", - "start": 11.42, - "end": 13.01, + "start": 11.64, + "end": 13.23, "f0_hz": 268.5, "note": "C4" }, { "t": "waiting", - "start": 13.01, - "end": 14.71, + "start": 13.23, + "end": 14.93, "f0_hz": 279.6, - "note": "C♯4" + "note": "C\u266f4" }, { "t": "very", - "start": 14.71, - "end": 16.29, + "start": 14.93, + "end": 16.51, "f0_hz": 236.5, - "note": "A♯3" + "note": "A\u266f3" }, { "t": "patiently", - "start": 16.29, - "end": 18.82, + "start": 16.51, + "end": 19.04, "f0_hz": 317.5, - "note": "D♯4" + "note": "D\u266f4" }, { "t": "for", - "start": 18.82, - "end": 19.78, + "start": 19.04, + "end": 20.0, "f0_hz": 319.3, - "note": "D♯4" + "note": "D\u266f4" }, { "t": "time", - "start": 19.78, - "end": 21.4, + "start": 20.0, + "end": 21.62, "f0_hz": 358.4, "note": "F4" }, { "t": "to", - "start": 21.4, - "end": 23.12, + "start": 21.62, + "end": 23.34, "f0_hz": 282.8, - "note": "C♯4" + "note": "C\u266f4" }, { "t": "pass", - "start": 23.12, - "end": 24.99, + "start": 23.34, + "end": 25.21, "f0_hz": 282.8, - "note": "C♯4" + "note": "C\u266f4" } ] }, @@ -465,14 +465,14 @@ "t": "are", "start": 0.51, "end": 0.68, "f0_hz": 206.5, - "note": "G♯3" + "note": "G\u266f3" }, { "t": "doing", "start": 0.85, "end": 1.14, "f0_hz": 303.1, - "note": "D♯4" + "note": "D\u266f4" }, { "t": "whistle", @@ -493,7 +493,7 @@ "t": "again", "start": 2.07, "end": 2.36, "f0_hz": 156.9, - "note": "D♯3" + "note": "D\u266f3" } ] }, @@ -510,7 +510,7 @@ "t": "Getting", "start": 3.14, "end": 4.4, "f0_hz": 308.4, - "note": "D♯4" + "note": "D\u266f4" }, { "t": "cur", @@ -524,21 +524,21 @@ "t": "led", "start": 4.96, "end": 5.46, "f0_hz": 236.5, - "note": "A♯3" + "note": "A\u266f3" }, { "t": "up", "start": 5.46, "end": 5.82, "f0_hz": 239.2, - "note": "A♯3" + "note": "A\u266f3" }, { "t": "in", "start": 5.82, "end": 6.18, "f0_hz": 310.2, - "note": "D♯4" + "note": "D\u266f4" }, { "t": "myself", @@ -552,14 +552,14 @@ "t": "I", "start": 7.25, "end": 7.43, "f0_hz": 207.1, - "note": "G♯3" + "note": "G\u266f3" }, { "t": "think", "start": 7.43, "end": 8.36, "f0_hz": 205.9, - "note": "G♯3" + "note": "G\u266f3" } ] }, @@ -576,21 +576,21 @@ "t": "Of", "start": 9.16, "end": 9.67, "f0_hz": 467.5, - "note": "A♯4" + "note": "A\u266f4" }, { "t": "a", "start": 9.67, "end": 9.92, "f0_hz": 463.5, - "note": "A♯4" + "note": "A\u266f4" }, { "t": "stone", "start": 9.92, "end": 11.19, "f0_hz": 409.3, - "note": "G♯4" + "note": "G\u266f4" } ] }, @@ -607,35 +607,35 @@ "t": "Of", "start": 9.16, "end": 9.67, "f0_hz": 467.5, - "note": "A♯4" + "note": "A\u266f4" }, { "t": "a", "start": 9.67, "end": 9.92, "f0_hz": 463.5, - "note": "A♯4" + "note": "A\u266f4" }, { "t": "stone", "start": 9.92, "end": 11.19, "f0_hz": 409.3, - "note": "G♯4" + "note": "G\u266f4" }, { "t": "just", "start": 11.19, "end": 12.22, "f0_hz": 313.8, - "note": "D♯4" + "note": "D\u266f4" }, { "t": "waiting", "start": 12.22, "end": 13.99, "f0_hz": 281.2, - "note": "C♯4" + "note": "C\u266f4" }, { "t": "very", @@ -649,7 +649,7 @@ "t": "patiently", "start": 15.01, "end": 17.3, "f0_hz": 312, - "note": "D♯4" + "note": "D\u266f4" } ] }, @@ -680,14 +680,14 @@ "t": "to", "start": 20.71, "end": 21.27, "f0_hz": 276.4, - "note": "C♯4" + "note": "C\u266f4" }, { "t": "pass", "start": 21.27, "end": 22.28, "f0_hz": 281.2, - "note": "C♯4" + "note": "C\u266f4" } ] }, @@ -712,7 +712,7 @@ "o-heres-loner": { "source": "6988619239657622790", "start": 0.18, "end": 4.5, - "words": "here's a whistlegraph by camille called loner — ready? (spoken)", + "words": "here's a whistlegraph by camille called loner \u2014 ready? (spoken)", "dur": 4.32, "median_f0_hz": 155.1, "word_f0": [ @@ -721,7 +721,7 @@ "t": "a", "start": 0.34, "end": 0.39, "f0_hz": 208.9, - "note": "G♯3" + "note": "G\u266f3" }, { "t": "Cam", @@ -735,7 +735,7 @@ "t": "ille", "start": 1.37, "end": 1.6, "f0_hz": 155.1, - "note": "D♯3" + "note": "D\u266f3" } ] }, @@ -759,7 +759,7 @@ "t": "cur", "start": 5.92, "end": 6.44, "f0_hz": 239.2, - "note": "A♯3" + "note": "A\u266f3" }, { "t": "led", @@ -773,21 +773,21 @@ "t": "up", "start": 6.95, "end": 7.65, "f0_hz": 204.7, - "note": "G♯3" + "note": "G\u266f3" }, { "t": "in", "start": 7.65, "end": 8.16, "f0_hz": 180.3, - "note": "F♯3" + "note": "F\u266f3" }, { "t": "myself", "start": 8.16, "end": 9.68, "f0_hz": 205.9, - "note": "G♯3" + "note": "G\u266f3" }, { "t": "I", @@ -801,7 +801,7 @@ "t": "think", "start": 10.23, "end": 11.04, "f0_hz": 141.4, - "note": "C♯3" + "note": "C\u266f3" }, { "t": "of", @@ -822,7 +822,7 @@ "t": "stone", "start": 12.06, "end": 13.59, "f0_hz": 315.7, - "note": "D♯4" + "note": "D\u266f4" }, { "t": "just", @@ -836,7 +836,7 @@ "t": "waiting", "start": 15.68, "end": 17.24, "f0_hz": 204.1, - "note": "G♯3" + "note": "G\u266f3" }, { "t": "very", @@ -857,7 +857,7 @@ "t": "for", "start": 21.52, "end": 22.51, "f0_hz": 271.6, - "note": "C♯4" + "note": "C\u266f4" }, { "t": "time", @@ -888,14 +888,14 @@ "t": "ib", "start": 0.49, "end": 0.67, "f0_hz": 278, - "note": "C♯4" + "note": "C\u266f4" }, { "t": "bing", "start": 0.67, "end": 1.57, "f0_hz": 276.4, - "note": "C♯4" + "note": "C\u266f4" }, { "t": "cur", @@ -916,21 +916,21 @@ "t": "up", "start": 2.91, "end": 3.36, "f0_hz": 202.3, - "note": "G♯3" + "note": "G\u266f3" }, { "t": "in", "start": 3.36, "end": 3.81, "f0_hz": 183.4, - "note": "F♯3" + "note": "F\u266f3" }, { "t": "myself", "start": 3.81, "end": 5.27, "f0_hz": 204.7, - "note": "G♯3" + "note": "G\u266f3" }, { "t": "I", @@ -951,14 +951,14 @@ "t": "of", "start": 6.6, "end": 7.14, "f0_hz": 362.6, - "note": "F♯4" + "note": "F\u266f4" }, { "t": "a", "start": 7.14, "end": 7.53, "f0_hz": 360.5, - "note": "F♯4" + "note": "F\u266f4" }, { "t": "stone", @@ -972,7 +972,7 @@ "t": "Just", "start": 9.48, "end": 10.51, "f0_hz": 202.9, - "note": "G♯3" + "note": "G\u266f3" }, { "t": "waiting", @@ -986,7 +986,7 @@ "t": "very", "start": 12.31, "end": 13.34, "f0_hz": 182.3, - "note": "F♯3" + "note": "F\u266f3" }, { "t": "patiently", @@ -1007,7 +1007,7 @@ "t": "time", "start": 16.76, "end": 18.21, "f0_hz": 136.6, - "note": "C♯3" + "note": "C\u266f3" }, { "t": "to", diff --git a/pop/loner/samples/.takecharts.json b/pop/loner/samples/.takecharts.json new file mode 100644 --- /dev/null +++ b/pop/loner/samples/.takecharts.json @@ -0,0 +1,3242 @@ +{ + "w-rq": { + "slice": { + "source": "corpus/rq", + "start": 0.0, + "end": 26.974, + "words": "the whole lyric, assembled from corpus", + "dur": 26.974, + "median_f0_hz": 121.4, + "word_f0": [ + { + "t": "sitting", + "start": 0.4, + "end": 1.794, + "f0_hz": 147.0, + "note": "D3" + }, + { + "t": "curled", + "start": 2.044, + "end": 3.8105, + "f0_hz": 116.8, + "note": "A#2" + }, + { + "t": "up", + "start": 4.0605, + "end": 4.2945, + "f0_hz": 146.7, + "note": "D3" + }, + { + "t": "in", + "start": 4.5445, + "end": 5.0885, + "f0_hz": 103.7, + "note": "G#2" + }, + { + "t": "myself", + "start": 5.3385, + "end": 6.97, + "f0_hz": 128.2, + "note": "C3" + }, + { + "t": "i", + "start": 7.22, + "end": 7.5565, + "f0_hz": 91.5, + "note": "F#2" + }, + { + "t": "think", + "start": 7.8065, + "end": 8.7505, + "f0_hz": 148.5, + "note": "D3" + }, + { + "t": "of", + "start": 9.0005, + "end": 9.817, + "f0_hz": 198.2, + "note": "G3" + }, + { + "t": "a", + "start": 10.067, + "end": 10.611, + "f0_hz": 198.6, + "note": "G3" + }, + { + "t": "stone", + "start": 10.861, + "end": 13.1975, + "f0_hz": 175.8, + "note": "F3" + }, + { + "t": "just", + "start": 13.4475, + "end": 14.9865, + "f0_hz": 112.0, + "note": "A2" + }, + { + "t": "waiting", + "start": 15.2365, + "end": 16.8305, + "f0_hz": 116.3, + "note": "A#2" + }, + { + "t": "very", + "start": 17.0805, + "end": 18.717, + "f0_hz": 103.0, + "note": "G#2" + }, + { + "t": "patiently", + "start": 18.967, + "end": 21.1585, + "f0_hz": 131.5, + "note": "C3" + }, + { + "t": "for", + "start": 21.4085, + "end": 22.055, + "f0_hz": 134.3, + "note": "C3" + }, + { + "t": "time", + "start": 22.305, + "end": 24.3415, + "f0_hz": 150.4, + "note": "D3" + }, + { + "t": "to", + "start": 24.5915, + "end": 25.153, + "f0_hz": 117.8, + "note": "A#2" + }, + { + "t": "pass", + "start": 25.403, + "end": 26.9745, + "f0_hz": 117.9, + "note": "A#2" + } + ] + }, + "align": { + "model": "corpus", + "text": "sitting curled up in myself i think of a stone just waiting very patiently for time to pass", + "words": [ + { + "t": "sitting", + "start": 0.4, + "end": 1.794, + "f0_hz": 147.0, + "note": "D3" + }, + { + "t": "curled", + "start": 2.044, + "end": 3.8105, + "f0_hz": 116.8, + "note": "A#2" + }, + { + "t": "up", + "start": 4.0605, + "end": 4.2945, + "f0_hz": 146.7, + "note": "D3" + }, + { + "t": "in", + "start": 4.5445, + "end": 5.0885, + "f0_hz": 103.7, + "note": "G#2" + }, + { + "t": "myself", + "start": 5.3385, + "end": 6.97, + "f0_hz": 128.2, + "note": "C3" + }, + { + "t": "i", + "start": 7.22, + "end": 7.5565, + "f0_hz": 91.5, + "note": "F#2" + }, + { + "t": "think", + "start": 7.8065, + "end": 8.7505, + "f0_hz": 148.5, + "note": "D3" + }, + { + "t": "of", + "start": 9.0005, + "end": 9.817, + "f0_hz": 198.2, + "note": "G3" + }, + { + "t": "a", + "start": 10.067, + "end": 10.611, + "f0_hz": 198.6, + "note": "G3" + }, + { + "t": "stone", + "start": 10.861, + "end": 13.1975, + "f0_hz": 175.8, + "note": "F3" + }, + { + "t": "just", + "start": 13.4475, + "end": 14.9865, + "f0_hz": 112.0, + "note": "A2" + }, + { + "t": "waiting", + "start": 15.2365, + "end": 16.8305, + "f0_hz": 116.3, + "note": "A#2" + }, + { + "t": "very", + "start": 17.0805, + "end": 18.717, + "f0_hz": 103.0, + "note": "G#2" + }, + { + "t": "patiently", + "start": 18.967, + "end": 21.1585, + "f0_hz": 131.5, + "note": "C3" + }, + { + "t": "for", + "start": 21.4085, + "end": 22.055, + "f0_hz": 134.3, + "note": "C3" + }, + { + "t": "time", + "start": 22.305, + "end": 24.3415, + "f0_hz": 150.4, + "note": "D3" + }, + { + "t": "to", + "start": 24.5915, + "end": 25.153, + "f0_hz": 117.8, + "note": "A#2" + }, + { + "t": "pass", + "start": 25.403, + "end": 26.9745, + "f0_hz": 117.9, + "note": "A#2" + } + ] + }, + "chart": { + "slice": "rq-line", + "beats": 60.0, + "lead": 0.0, + "durs": { + "0": 2.0, + "1": 2.0, + "2": 1.91, + "3": 2.09, + "4": 2.0, + "5": 1.5, + "6": 2.5, + "7": 2.0, + "8": 2.0, + "9": 4.0, + "10": 1.75, + "11": 4.25, + "12": 4.0, + "13": 2.0, + "14": 2.0, + "15": 2.0, + "16": 2.0, + "17": 2.0, + "18": 2.0, + "19": 2.0, + "20": 2.0, + "21": 4.0, + "22": 4.0, + "23": 4.0 + }, + "melody": [ + 7, + 5, + 3, + 2, + 0, + 5, + 2, + -2, + -5, + 12, + 10, + 5, + 2, + 3, + 2, + 0, + -2, + 7, + 5, + 3, + 5, + 7, + 3, + 3 + ], + "sylls": { + "0": [ + [ + null, + "sitting\u00b7a" + ], + [ + 1.615, + "sitting\u00b7b" + ] + ], + "4": [ + [ + null, + "my" + ], + [ + 6.0885, + "self" + ] + ], + "11": [ + [ + null, + "wait" + ], + [ + 16.1615, + "ing" + ] + ], + "12": [ + [ + null, + "ve" + ], + [ + 18.4955, + "ry" + ] + ], + "13": [ + [ + null, + "pa" + ], + [ + 19.802, + "tient" + ], + [ + 20.342, + "ly" + ] + ] + }, + "times": { + "0": 0.4, + "1": 2.044, + "2": 4.0605, + "3": 4.5445, + "4": 5.3385, + "5": 7.22, + "6": 7.8065, + "7": 9.0005, + "8": 10.067, + "9": 10.861, + "10": 13.4475, + "11": 15.2365, + "12": 17.0805, + "13": 18.967, + "14": 21.4085, + "15": 22.305, + "16": 24.5915, + "17": 25.403 + }, + "end": 26.9745 + }, + "name": "rq-line" + }, + "w-sh": { + "slice": { + "source": "corpus/sh", + "start": 0.0, + "end": 26.974, + "words": "the whole lyric, assembled from corpus", + "dur": 26.974, + "median_f0_hz": 121.4, + "word_f0": [ + { + "t": "sitting", + "start": 0.4, + "end": 2.044, + "f0_hz": 234.7, + "note": "A#3" + }, + { + "t": "curled", + "start": 2.294, + "end": 3.7905, + "f0_hz": 110.2, + "note": "A2" + }, + { + "t": "up", + "start": 4.0405, + "end": 4.512, + "f0_hz": 0.0, + "note": "?" + }, + { + "t": "in", + "start": 4.762, + "end": 5.3985, + "f0_hz": 179.5, + "note": "F3" + }, + { + "t": "myself", + "start": 5.6485, + "end": 7.195, + "f0_hz": 110.5, + "note": "A2" + }, + { + "t": "i", + "start": 7.445, + "end": 7.734, + "f0_hz": 168.1, + "note": "E3" + }, + { + "t": "think", + "start": 7.984, + "end": 8.943, + "f0_hz": 165.2, + "note": "E3" + }, + { + "t": "of", + "start": 9.193, + "end": 9.827, + "f0_hz": 177.7, + "note": "F3" + }, + { + "t": "a", + "start": 10.077, + "end": 10.4084, + "f0_hz": 180.9, + "note": "F#3" + }, + { + "t": "stone", + "start": 10.6584, + "end": 12.7149, + "f0_hz": 153.3, + "note": "D#3" + }, + { + "t": "just", + "start": 12.9649, + "end": 14.5539, + "f0_hz": 104.6, + "note": "G#2" + }, + { + "t": "waiting", + "start": 14.8039, + "end": 16.5254, + "f0_hz": 108.9, + "note": "A2" + }, + { + "t": "very", + "start": 16.7754, + "end": 17.9519, + "f0_hz": 175.9, + "note": "F3" + }, + { + "t": "patiently", + "start": 18.2019, + "end": 20.6184, + "f0_hz": 120.1, + "note": "B2" + }, + { + "t": "for", + "start": 20.8684, + "end": 21.785, + "f0_hz": 122.3, + "note": "B2" + }, + { + "t": "time", + "start": 22.035, + "end": 23.274, + "f0_hz": 136.6, + "note": "C#3" + }, + { + "t": "to", + "start": 23.524, + "end": 24.6255, + "f0_hz": 108.3, + "note": "A2" + }, + { + "t": "pass", + "start": 24.8755, + "end": 26.9745, + "f0_hz": 108.3, + "note": "A2" + } + ] + }, + "align": { + "model": "corpus", + "text": "sitting curled up in myself i think of a stone just waiting very patiently for time to pass", + "words": [ + { + "t": "sitting", + "start": 0.4, + "end": 2.044, + "f0_hz": 234.7, + "note": "A#3" + }, + { + "t": "curled", + "start": 2.294, + "end": 3.7905, + "f0_hz": 110.2, + "note": "A2" + }, + { + "t": "up", + "start": 4.0405, + "end": 4.512, + "f0_hz": 0.0, + "note": "?" + }, + { + "t": "in", + "start": 4.762, + "end": 5.3985, + "f0_hz": 179.5, + "note": "F3" + }, + { + "t": "myself", + "start": 5.6485, + "end": 7.195, + "f0_hz": 110.5, + "note": "A2" + }, + { + "t": "i", + "start": 7.445, + "end": 7.734, + "f0_hz": 168.1, + "note": "E3" + }, + { + "t": "think", + "start": 7.984, + "end": 8.943, + "f0_hz": 165.2, + "note": "E3" + }, + { + "t": "of", + "start": 9.193, + "end": 9.827, + "f0_hz": 177.7, + "note": "F3" + }, + { + "t": "a", + "start": 10.077, + "end": 10.4084, + "f0_hz": 180.9, + "note": "F#3" + }, + { + "t": "stone", + "start": 10.6584, + "end": 12.7149, + "f0_hz": 153.3, + "note": "D#3" + }, + { + "t": "just", + "start": 12.9649, + "end": 14.5539, + "f0_hz": 104.6, + "note": "G#2" + }, + { + "t": "waiting", + "start": 14.8039, + "end": 16.5254, + "f0_hz": 108.9, + "note": "A2" + }, + { + "t": "very", + "start": 16.7754, + "end": 17.9519, + "f0_hz": 175.9, + "note": "F3" + }, + { + "t": "patiently", + "start": 18.2019, + "end": 20.6184, + "f0_hz": 120.1, + "note": "B2" + }, + { + "t": "for", + "start": 20.8684, + "end": 21.785, + "f0_hz": 122.3, + "note": "B2" + }, + { + "t": "time", + "start": 22.035, + "end": 23.274, + "f0_hz": 136.6, + "note": "C#3" + }, + { + "t": "to", + "start": 23.524, + "end": 24.6255, + "f0_hz": 108.3, + "note": "A2" + }, + { + "t": "pass", + "start": 24.8755, + "end": 26.9745, + "f0_hz": 108.3, + "note": "A2" + } + ] + }, + "chart": { + "slice": "sh-line", + "beats": 60.0, + "lead": 0.0, + "durs": { + "0": 2.0, + "1": 2.0, + "2": 1.91, + "3": 2.09, + "4": 2.0, + "5": 1.5, + "6": 2.5, + "7": 2.0, + "8": 2.0, + "9": 4.0, + "10": 1.75, + "11": 4.25, + "12": 4.0, + "13": 2.0, + "14": 2.0, + "15": 2.0, + "16": 2.0, + "17": 2.0, + "18": 2.0, + "19": 2.0, + "20": 2.0, + "21": 4.0, + "22": 4.0, + "23": 4.0 + }, + "melody": [ + 7, + 5, + 3, + 2, + 0, + 5, + 2, + -2, + -5, + 12, + 10, + 5, + 2, + 3, + 2, + 0, + -2, + 7, + 5, + 3, + 5, + 7, + 3, + 3 + ], + "sylls": { + "0": [ + [ + null, + "sitting\u00b7a" + ], + [ + 1.48, + "sitting\u00b7b" + ] + ], + "4": [ + [ + null, + "my" + ], + [ + 6.9785, + "self" + ] + ], + "11": [ + [ + null, + "wait" + ], + [ + 15.0789, + "ing" + ] + ], + "12": [ + [ + null, + "ve" + ], + [ + 17.7654, + "ry" + ] + ], + "13": [ + [ + null, + "pa" + ], + [ + 18.5369, + "tient" + ], + [ + 19.8169, + "ly" + ] + ] + }, + "times": { + "0": 0.4, + "1": 2.294, + "2": 4.0405, + "3": 4.762, + "4": 5.6485, + "5": 7.445, + "6": 7.984, + "7": 9.193, + "8": 10.077, + "9": 10.6584, + "10": 12.9649, + "11": 14.8039, + "12": 16.7754, + "13": 18.2019, + "14": 20.8684, + "15": 22.035, + "16": 23.524, + "17": 24.8755 + }, + "end": 26.9745 + }, + "name": "sh-line" + }, + "w-lg": { + "slice": { + "source": "corpus/lg", + "start": 0.0, + "end": 26.812, + "words": "the whole lyric, assembled from corpus", + "dur": 26.812, + "median_f0_hz": 229.4, + "word_f0": [ + { + "t": "sitting", + "start": 0.4, + "end": 1.974, + "f0_hz": 285.9, + "note": "D4" + }, + { + "t": "curled", + "start": 2.224, + "end": 3.6605, + "f0_hz": 226.8, + "note": "A#3" + }, + { + "t": "up", + "start": 3.9105, + "end": 4.4445, + "f0_hz": 133.7, + "note": "C3" + }, + { + "t": "in", + "start": 4.6945, + "end": 5.2835, + "f0_hz": 192.3, + "note": "G3" + }, + { + "t": "myself", + "start": 5.5335, + "end": 7.25, + "f0_hz": 222.4, + "note": "A3" + }, + { + "t": "i", + "start": 7.5, + "end": 7.6965, + "f0_hz": 171.7, + "note": "F3" + }, + { + "t": "think", + "start": 7.9465, + "end": 8.8055, + "f0_hz": 171.4, + "note": "F3" + }, + { + "t": "of", + "start": 9.0555, + "end": 9.9345, + "f0_hz": 375.1, + "note": "F#4" + }, + { + "t": "a", + "start": 10.1845, + "end": 10.676, + "f0_hz": 378.4, + "note": "F#4" + }, + { + "t": "stone", + "start": 10.926, + "end": 13.4075, + "f0_hz": 325.3, + "note": "E4" + }, + { + "t": "just", + "start": 13.6575, + "end": 15.054, + "f0_hz": 214.7, + "note": "A3" + }, + { + "t": "waiting", + "start": 15.304, + "end": 17.028, + "f0_hz": 218.2, + "note": "A3" + }, + { + "t": "very", + "start": 17.278, + "end": 18.5245, + "f0_hz": 188.8, + "note": "F#3" + }, + { + "t": "patiently", + "start": 18.7745, + "end": 20.986, + "f0_hz": 247.5, + "note": "B3" + }, + { + "t": "for", + "start": 21.236, + "end": 22.205, + "f0_hz": 255.2, + "note": "C4" + }, + { + "t": "time", + "start": 22.455, + "end": 23.6515, + "f0_hz": 280.7, + "note": "C#4" + }, + { + "t": "to", + "start": 23.9015, + "end": 24.8605, + "f0_hz": 222.1, + "note": "A3" + }, + { + "t": "pass", + "start": 25.1105, + "end": 26.812, + "f0_hz": 221.3, + "note": "A3" + } + ] + }, + "align": { + "model": "corpus", + "text": "sitting curled up in myself i think of a stone just waiting very patiently for time to pass", + "words": [ + { + "t": "sitting", + "start": 0.4, + "end": 1.974, + "f0_hz": 285.9, + "note": "D4" + }, + { + "t": "curled", + "start": 2.224, + "end": 3.6605, + "f0_hz": 226.8, + "note": "A#3" + }, + { + "t": "up", + "start": 3.9105, + "end": 4.4445, + "f0_hz": 133.7, + "note": "C3" + }, + { + "t": "in", + "start": 4.6945, + "end": 5.2835, + "f0_hz": 192.3, + "note": "G3" + }, + { + "t": "myself", + "start": 5.5335, + "end": 7.25, + "f0_hz": 222.4, + "note": "A3" + }, + { + "t": "i", + "start": 7.5, + "end": 7.6965, + "f0_hz": 171.7, + "note": "F3" + }, + { + "t": "think", + "start": 7.9465, + "end": 8.8055, + "f0_hz": 171.4, + "note": "F3" + }, + { + "t": "of", + "start": 9.0555, + "end": 9.9345, + "f0_hz": 375.1, + "note": "F#4" + }, + { + "t": "a", + "start": 10.1845, + "end": 10.676, + "f0_hz": 378.4, + "note": "F#4" + }, + { + "t": "stone", + "start": 10.926, + "end": 13.4075, + "f0_hz": 325.3, + "note": "E4" + }, + { + "t": "just", + "start": 13.6575, + "end": 15.054, + "f0_hz": 214.7, + "note": "A3" + }, + { + "t": "waiting", + "start": 15.304, + "end": 17.028, + "f0_hz": 218.2, + "note": "A3" + }, + { + "t": "very", + "start": 17.278, + "end": 18.5245, + "f0_hz": 188.8, + "note": "F#3" + }, + { + "t": "patiently", + "start": 18.7745, + "end": 20.986, + "f0_hz": 247.5, + "note": "B3" + }, + { + "t": "for", + "start": 21.236, + "end": 22.205, + "f0_hz": 255.2, + "note": "C4" + }, + { + "t": "time", + "start": 22.455, + "end": 23.6515, + "f0_hz": 280.7, + "note": "C#4" + }, + { + "t": "to", + "start": 23.9015, + "end": 24.8605, + "f0_hz": 222.1, + "note": "A3" + }, + { + "t": "pass", + "start": 25.1105, + "end": 26.812, + "f0_hz": 221.3, + "note": "A3" + } + ] + }, + "chart": { + "slice": "lg-line", + "beats": 60.0, + "lead": 0.0, + "durs": { + "0": 2.0, + "1": 2.0, + "2": 1.91, + "3": 2.09, + "4": 2.0, + "5": 1.5, + "6": 2.5, + "7": 2.0, + "8": 2.0, + "9": 4.0, + "10": 1.75, + "11": 4.25, + "12": 4.0, + "13": 2.0, + "14": 2.0, + "15": 2.0, + "16": 2.0, + "17": 2.0, + "18": 2.0, + "19": 2.0, + "20": 2.0, + "21": 4.0, + "22": 4.0, + "23": 4.0 + }, + "melody": [ + 7, + 5, + 3, + 2, + 0, + 5, + 2, + -2, + -5, + 12, + 10, + 5, + 2, + 3, + 2, + 0, + -2, + 7, + 5, + 3, + 5, + 7, + 3, + 3 + ], + "sylls": { + "0": [ + [ + null, + "sitting\u00b7a" + ], + [ + 1.345, + "sitting\u00b7b" + ] + ], + "4": [ + [ + null, + "my" + ], + [ + 7.0035, + "self" + ] + ], + "11": [ + [ + null, + "wait" + ], + [ + 16.189, + "ing" + ] + ], + "12": [ + [ + null, + "ve" + ], + [ + 18.358, + "ry" + ] + ], + "13": [ + [ + null, + "pa" + ], + [ + 19.6445, + "tient" + ], + [ + 20.2445, + "ly" + ] + ] + }, + "times": { + "0": 0.4, + "1": 2.224, + "2": 3.9105, + "3": 4.6945, + "4": 5.5335, + "5": 7.5, + "6": 7.9465, + "7": 9.0555, + "8": 10.1845, + "9": 10.926, + "10": 13.6575, + "11": 15.304, + "12": 17.278, + "13": 18.7745, + "14": 21.236, + "15": 22.455, + "16": 23.9015, + "17": 25.1105 + }, + "end": 26.812 + }, + "name": "lg-line" + }, + "w-pf": { + "slice": { + "source": "corpus/pf", + "start": 0.0, + "end": 26.529, + "words": "the whole lyric, assembled from corpus", + "dur": 26.529, + "median_f0_hz": 120.7, + "word_f0": [ + { + "t": "sitting", + "start": 0.4, + "end": 1.9665, + "f0_hz": 134.4, + "note": "C3" + }, + { + "t": "curled", + "start": 2.2165, + "end": 3.713, + "f0_hz": 109.9, + "note": "A2" + }, + { + "t": "up", + "start": 3.963, + "end": 4.4895, + "f0_hz": 198.2, + "note": "G3" + }, + { + "t": "in", + "start": 4.7395, + "end": 5.376, + "f0_hz": 105.4, + "note": "G#2" + }, + { + "t": "myself", + "start": 5.626, + "end": 7.1175, + "f0_hz": 112.1, + "note": "A2" + }, + { + "t": "i", + "start": 7.3675, + "end": 7.569, + "f0_hz": 0.0, + "note": "?" + }, + { + "t": "think", + "start": 7.819, + "end": 8.8655, + "f0_hz": 0.0, + "note": "?" + }, + { + "t": "of", + "start": 9.1155, + "end": 9.8545, + "f0_hz": 179.5, + "note": "F3" + }, + { + "t": "a", + "start": 10.1045, + "end": 10.4285, + "f0_hz": 181.0, + "note": "F#3" + }, + { + "t": "stone", + "start": 10.6785, + "end": 12.6575, + "f0_hz": 133.0, + "note": "C3" + }, + { + "t": "just", + "start": 12.9075, + "end": 14.179, + "f0_hz": 104.0, + "note": "G#2" + }, + { + "t": "waiting", + "start": 14.429, + "end": 15.9555, + "f0_hz": 109.4, + "note": "A2" + }, + { + "t": "very", + "start": 16.2055, + "end": 17.4545, + "f0_hz": 179.3, + "note": "F3" + }, + { + "t": "patiently", + "start": 17.7045, + "end": 20.1735, + "f0_hz": 120.9, + "note": "B2" + }, + { + "t": "for", + "start": 20.4235, + "end": 21.34, + "f0_hz": 122.5, + "note": "B2" + }, + { + "t": "time", + "start": 21.59, + "end": 22.829, + "f0_hz": 136.5, + "note": "C#3" + }, + { + "t": "to", + "start": 23.079, + "end": 24.053, + "f0_hz": 108.2, + "note": "A2" + }, + { + "t": "pass", + "start": 24.303, + "end": 26.5295, + "f0_hz": 107.7, + "note": "A2" + } + ] + }, + "align": { + "model": "corpus", + "text": "sitting curled up in myself i think of a stone just waiting very patiently for time to pass", + "words": [ + { + "t": "sitting", + "start": 0.4, + "end": 1.9665, + "f0_hz": 134.4, + "note": "C3" + }, + { + "t": "curled", + "start": 2.2165, + "end": 3.713, + "f0_hz": 109.9, + "note": "A2" + }, + { + "t": "up", + "start": 3.963, + "end": 4.4895, + "f0_hz": 198.2, + "note": "G3" + }, + { + "t": "in", + "start": 4.7395, + "end": 5.376, + "f0_hz": 105.4, + "note": "G#2" + }, + { + "t": "myself", + "start": 5.626, + "end": 7.1175, + "f0_hz": 112.1, + "note": "A2" + }, + { + "t": "i", + "start": 7.3675, + "end": 7.569, + "f0_hz": 0.0, + "note": "?" + }, + { + "t": "think", + "start": 7.819, + "end": 8.8655, + "f0_hz": 0.0, + "note": "?" + }, + { + "t": "of", + "start": 9.1155, + "end": 9.8545, + "f0_hz": 179.5, + "note": "F3" + }, + { + "t": "a", + "start": 10.1045, + "end": 10.4285, + "f0_hz": 181.0, + "note": "F#3" + }, + { + "t": "stone", + "start": 10.6785, + "end": 12.6575, + "f0_hz": 133.0, + "note": "C3" + }, + { + "t": "just", + "start": 12.9075, + "end": 14.179, + "f0_hz": 104.0, + "note": "G#2" + }, + { + "t": "waiting", + "start": 14.429, + "end": 15.9555, + "f0_hz": 109.4, + "note": "A2" + }, + { + "t": "very", + "start": 16.2055, + "end": 17.4545, + "f0_hz": 179.3, + "note": "F3" + }, + { + "t": "patiently", + "start": 17.7045, + "end": 20.1735, + "f0_hz": 120.9, + "note": "B2" + }, + { + "t": "for", + "start": 20.4235, + "end": 21.34, + "f0_hz": 122.5, + "note": "B2" + }, + { + "t": "time", + "start": 21.59, + "end": 22.829, + "f0_hz": 136.5, + "note": "C#3" + }, + { + "t": "to", + "start": 23.079, + "end": 24.053, + "f0_hz": 108.2, + "note": "A2" + }, + { + "t": "pass", + "start": 24.303, + "end": 26.5295, + "f0_hz": 107.7, + "note": "A2" + } + ] + }, + "chart": { + "slice": "pf-line", + "beats": 60.0, + "lead": 0.0, + "durs": { + "0": 2.0, + "1": 2.0, + "2": 1.91, + "3": 2.09, + "4": 2.0, + "5": 1.5, + "6": 2.5, + "7": 2.0, + "8": 2.0, + "9": 4.0, + "10": 1.75, + "11": 4.25, + "12": 4.0, + "13": 2.0, + "14": 2.0, + "15": 2.0, + "16": 2.0, + "17": 2.0, + "18": 2.0, + "19": 2.0, + "20": 2.0, + "21": 4.0, + "22": 4.0, + "23": 4.0 + }, + "melody": [ + 7, + 5, + 3, + 2, + 0, + 5, + 2, + -2, + -5, + 12, + 10, + 5, + 2, + 3, + 2, + 0, + -2, + 7, + 5, + 3, + 5, + 7, + 3, + 3 + ], + "sylls": { + "0": [ + [ + null, + "sitting\u00b7a" + ], + [ + 0.945, + "sitting\u00b7b" + ] + ], + "4": [ + [ + null, + "my" + ], + [ + 6.396, + "self" + ] + ], + "11": [ + [ + null, + "wait" + ], + [ + 14.634, + "ing" + ] + ], + "12": [ + [ + null, + "ve" + ], + [ + 17.2605, + "ry" + ] + ], + "13": [ + [ + null, + "pa" + ], + [ + 18.0945, + "tient" + ], + [ + 19.3745, + "ly" + ] + ] + }, + "times": { + "0": 0.4, + "1": 2.2165, + "2": 3.963, + "3": 4.7395, + "4": 5.626, + "5": 7.3675, + "6": 7.819, + "7": 9.1155, + "8": 10.1045, + "9": 10.6785, + "10": 12.9075, + "11": 14.429, + "12": 16.2055, + "13": 17.7045, + "14": 20.4235, + "15": 21.59, + "16": 23.079, + "17": 24.303 + }, + "end": 26.5295 + }, + "name": "pf-line" + }, + "w-rd": { + "slice": { + "source": "corpus/rd", + "start": 0.0, + "end": 24.505, + "words": "the whole lyric, assembled from corpus", + "dur": 24.505, + "median_f0_hz": 126.6, + "word_f0": [ + { + "t": "sitting", + "start": 0.4, + "end": 2.0365, + "f0_hz": 128.7, + "note": "C3" + }, + { + "t": "curled", + "start": 2.2865, + "end": 3.7155, + "f0_hz": 113.4, + "note": "A#2" + }, + { + "t": "up", + "start": 3.9655, + "end": 4.5045, + "f0_hz": 98.6, + "note": "G2" + }, + { + "t": "in", + "start": 4.7545, + "end": 5.126, + "f0_hz": 99.8, + "note": "G2" + }, + { + "t": "myself", + "start": 5.376, + "end": 6.9275, + "f0_hz": 126.0, + "note": "B2" + }, + { + "t": "i", + "start": 7.1775, + "end": 7.3965, + "f0_hz": 97.5, + "note": "G2" + }, + { + "t": "think", + "start": 7.6465, + "end": 8.3355, + "f0_hz": 184.2, + "note": "F#3" + }, + { + "t": "of", + "start": 8.5855, + "end": 9.362, + "f0_hz": 194.4, + "note": "G3" + }, + { + "t": "a", + "start": 9.612, + "end": 9.791, + "f0_hz": 173.0, + "note": "F3" + }, + { + "t": "stone", + "start": 10.041, + "end": 11.63, + "f0_hz": 128.6, + "note": "C3" + }, + { + "t": "just", + "start": 11.88, + "end": 13.069, + "f0_hz": 109.0, + "note": "A2" + }, + { + "t": "waiting", + "start": 13.319, + "end": 15.3205, + "f0_hz": 112.1, + "note": "A2" + }, + { + "t": "very", + "start": 15.5705, + "end": 16.6945, + "f0_hz": 184.6, + "note": "F#3" + }, + { + "t": "patiently", + "start": 16.9445, + "end": 19.5985, + "f0_hz": 129.9, + "note": "C3" + }, + { + "t": "for", + "start": 19.8485, + "end": 20.6725, + "f0_hz": 129.0, + "note": "C3" + }, + { + "t": "time", + "start": 20.9225, + "end": 22.139, + "f0_hz": 143.0, + "note": "D3" + }, + { + "t": "to", + "start": 22.389, + "end": 23.118, + "f0_hz": 113.0, + "note": "A2" + }, + { + "t": "pass", + "start": 23.368, + "end": 24.5045, + "f0_hz": 115.0, + "note": "A#2" + } + ] + }, + "align": { + "model": "corpus", + "text": "sitting curled up in myself i think of a stone just waiting very patiently for time to pass", + "words": [ + { + "t": "sitting", + "start": 0.4, + "end": 2.0365, + "f0_hz": 128.7, + "note": "C3" + }, + { + "t": "curled", + "start": 2.2865, + "end": 3.7155, + "f0_hz": 113.4, + "note": "A#2" + }, + { + "t": "up", + "start": 3.9655, + "end": 4.5045, + "f0_hz": 98.6, + "note": "G2" + }, + { + "t": "in", + "start": 4.7545, + "end": 5.126, + "f0_hz": 99.8, + "note": "G2" + }, + { + "t": "myself", + "start": 5.376, + "end": 6.9275, + "f0_hz": 126.0, + "note": "B2" + }, + { + "t": "i", + "start": 7.1775, + "end": 7.3965, + "f0_hz": 97.5, + "note": "G2" + }, + { + "t": "think", + "start": 7.6465, + "end": 8.3355, + "f0_hz": 184.2, + "note": "F#3" + }, + { + "t": "of", + "start": 8.5855, + "end": 9.362, + "f0_hz": 194.4, + "note": "G3" + }, + { + "t": "a", + "start": 9.612, + "end": 9.791, + "f0_hz": 173.0, + "note": "F3" + }, + { + "t": "stone", + "start": 10.041, + "end": 11.63, + "f0_hz": 128.6, + "note": "C3" + }, + { + "t": "just", + "start": 11.88, + "end": 13.069, + "f0_hz": 109.0, + "note": "A2" + }, + { + "t": "waiting", + "start": 13.319, + "end": 15.3205, + "f0_hz": 112.1, + "note": "A2" + }, + { + "t": "very", + "start": 15.5705, + "end": 16.6945, + "f0_hz": 184.6, + "note": "F#3" + }, + { + "t": "patiently", + "start": 16.9445, + "end": 19.5985, + "f0_hz": 129.9, + "note": "C3" + }, + { + "t": "for", + "start": 19.8485, + "end": 20.6725, + "f0_hz": 129.0, + "note": "C3" + }, + { + "t": "time", + "start": 20.9225, + "end": 22.139, + "f0_hz": 143.0, + "note": "D3" + }, + { + "t": "to", + "start": 22.389, + "end": 23.118, + "f0_hz": 113.0, + "note": "A2" + }, + { + "t": "pass", + "start": 23.368, + "end": 24.5045, + "f0_hz": 115.0, + "note": "A#2" + } + ] + }, + "chart": { + "slice": "rd-line", + "beats": 60.0, + "lead": 0.0, + "durs": { + "0": 2.0, + "1": 2.0, + "2": 1.91, + "3": 2.09, + "4": 2.0, + "5": 1.5, + "6": 2.5, + "7": 2.0, + "8": 2.0, + "9": 4.0, + "10": 1.75, + "11": 4.25, + "12": 4.0, + "13": 2.0, + "14": 2.0, + "15": 2.0, + "16": 2.0, + "17": 2.0, + "18": 2.0, + "19": 2.0, + "20": 2.0, + "21": 4.0, + "22": 4.0, + "23": 4.0 + }, + "melody": [ + 7, + 5, + 3, + 2, + 0, + 5, + 2, + -2, + -5, + 12, + 10, + 5, + 2, + 3, + 2, + 0, + -2, + 7, + 5, + 3, + 5, + 7, + 3, + 3 + ], + "sylls": { + "0": [ + [ + null, + "sitting\u00b7a" + ], + [ + 1.665, + "sitting\u00b7b" + ] + ], + "4": [ + [ + null, + "my" + ], + [ + 6.606, + "self" + ] + ], + "11": [ + [ + null, + "wait" + ], + [ + 13.674, + "ing" + ] + ], + "12": [ + [ + null, + "ve" + ], + [ + 16.3155, + "ry" + ] + ], + "13": [ + [ + null, + "pa" + ], + [ + 18.0295, + "tient" + ], + [ + 18.6195, + "ly" + ] + ] + }, + "times": { + "0": 0.4, + "1": 2.2865, + "2": 3.9655, + "3": 4.7545, + "4": 5.376, + "5": 7.1775, + "6": 7.6465, + "7": 8.5855, + "8": 9.612, + "9": 10.041, + "10": 11.88, + "11": 13.319, + "12": 15.5705, + "13": 16.9445, + "14": 19.8485, + "15": 20.9225, + "16": 22.389, + "17": 23.368 + }, + "end": 24.5045 + }, + "name": "rd-line" + }, + "w-cp": { + "slice": { + "source": "corpus/cp", + "start": 0.0, + "end": 22.062, + "words": "the whole lyric, assembled from corpus", + "dur": 22.062, + "median_f0_hz": 149.3, + "word_f0": [ + { + "t": "sitting", + "start": 0.4, + "end": 1.299, + "f0_hz": 193.1, + "note": "G3" + }, + { + "t": "curled", + "start": 1.549, + "end": 2.5305, + "f0_hz": 163.7, + "note": "E3" + }, + { + "t": "up", + "start": 2.7805, + "end": 3.152, + "f0_hz": 134.3, + "note": "C3" + }, + { + "t": "in", + "start": 3.402, + "end": 3.646, + "f0_hz": 167.0, + "note": "E3" + }, + { + "t": "myself", + "start": 3.896, + "end": 5.005, + "f0_hz": 167.2, + "note": "E3" + }, + { + "t": "i", + "start": 5.255, + "end": 5.5765, + "f0_hz": 123.5, + "note": "B2" + }, + { + "t": "think", + "start": 5.8265, + "end": 6.518, + "f0_hz": 133.2, + "note": "C3" + }, + { + "t": "of", + "start": 6.768, + "end": 7.8345, + "f0_hz": 252.5, + "note": "B3" + }, + { + "t": "a", + "start": 8.0845, + "end": 8.456, + "f0_hz": 216.8, + "note": "A3" + }, + { + "t": "stone", + "start": 8.706, + "end": 9.31, + "f0_hz": 170.4, + "note": "F3" + }, + { + "t": "just", + "start": 9.56, + "end": 10.704, + "f0_hz": 166.8, + "note": "E3" + }, + { + "t": "waiting", + "start": 10.954, + "end": 13.388, + "f0_hz": 151.3, + "note": "D#3" + }, + { + "t": "very", + "start": 13.638, + "end": 14.447, + "f0_hz": 126.9, + "note": "B2" + }, + { + "t": "patiently", + "start": 14.697, + "end": 17.4285, + "f0_hz": 132.1, + "note": "C3" + }, + { + "t": "for", + "start": 17.6785, + "end": 18.385, + "f0_hz": 148.4, + "note": "D3" + }, + { + "t": "time", + "start": 18.635, + "end": 19.769, + "f0_hz": 120.6, + "note": "B2" + }, + { + "t": "to", + "start": 20.019, + "end": 20.6605, + "f0_hz": 124.5, + "note": "B2" + }, + { + "t": "pass", + "start": 20.9105, + "end": 22.062, + "f0_hz": 0.0, + "note": "?" + } + ] + }, + "align": { + "model": "corpus", + "text": "sitting curled up in myself i think of a stone just waiting very patiently for time to pass", + "words": [ + { + "t": "sitting", + "start": 0.4, + "end": 1.299, + "f0_hz": 193.1, + "note": "G3" + }, + { + "t": "curled", + "start": 1.549, + "end": 2.5305, + "f0_hz": 163.7, + "note": "E3" + }, + { + "t": "up", + "start": 2.7805, + "end": 3.152, + "f0_hz": 134.3, + "note": "C3" + }, + { + "t": "in", + "start": 3.402, + "end": 3.646, + "f0_hz": 167.0, + "note": "E3" + }, + { + "t": "myself", + "start": 3.896, + "end": 5.005, + "f0_hz": 167.2, + "note": "E3" + }, + { + "t": "i", + "start": 5.255, + "end": 5.5765, + "f0_hz": 123.5, + "note": "B2" + }, + { + "t": "think", + "start": 5.8265, + "end": 6.518, + "f0_hz": 133.2, + "note": "C3" + }, + { + "t": "of", + "start": 6.768, + "end": 7.8345, + "f0_hz": 252.5, + "note": "B3" + }, + { + "t": "a", + "start": 8.0845, + "end": 8.456, + "f0_hz": 216.8, + "note": "A3" + }, + { + "t": "stone", + "start": 8.706, + "end": 9.31, + "f0_hz": 170.4, + "note": "F3" + }, + { + "t": "just", + "start": 9.56, + "end": 10.704, + "f0_hz": 166.8, + "note": "E3" + }, + { + "t": "waiting", + "start": 10.954, + "end": 13.388, + "f0_hz": 151.3, + "note": "D#3" + }, + { + "t": "very", + "start": 13.638, + "end": 14.447, + "f0_hz": 126.9, + "note": "B2" + }, + { + "t": "patiently", + "start": 14.697, + "end": 17.4285, + "f0_hz": 132.1, + "note": "C3" + }, + { + "t": "for", + "start": 17.6785, + "end": 18.385, + "f0_hz": 148.4, + "note": "D3" + }, + { + "t": "time", + "start": 18.635, + "end": 19.769, + "f0_hz": 120.6, + "note": "B2" + }, + { + "t": "to", + "start": 20.019, + "end": 20.6605, + "f0_hz": 124.5, + "note": "B2" + }, + { + "t": "pass", + "start": 20.9105, + "end": 22.062, + "f0_hz": 0.0, + "note": "?" + } + ] + }, + "chart": { + "slice": "cp-line", + "beats": 60.0, + "lead": 0.0, + "durs": { + "0": 2.0, + "1": 2.0, + "2": 1.91, + "3": 2.09, + "4": 2.0, + "5": 1.5, + "6": 2.5, + "7": 2.0, + "8": 2.0, + "9": 4.0, + "10": 1.75, + "11": 4.25, + "12": 4.0, + "13": 2.0, + "14": 2.0, + "15": 2.0, + "16": 2.0, + "17": 2.0, + "18": 2.0, + "19": 2.0, + "20": 2.0, + "21": 4.0, + "22": 4.0, + "23": 4.0 + }, + "melody": [ + 7, + 5, + 3, + 2, + 0, + 5, + 2, + -2, + -5, + 12, + 10, + 5, + 2, + 3, + 2, + 0, + -2, + 7, + 5, + 3, + 5, + 7, + 3, + 3 + ], + "sylls": { + "0": [ + [ + null, + "sitting\u00b7a" + ], + [ + 0.825, + "sitting\u00b7b" + ] + ], + "4": [ + [ + null, + "my" + ], + [ + 4.846, + "self" + ] + ], + "11": [ + [ + null, + "wait" + ], + [ + 11.664, + "ing" + ] + ], + "12": [ + [ + null, + "ve" + ], + [ + 14.348, + "ry" + ] + ], + "13": [ + [ + null, + "pa" + ], + [ + 15.672, + "tient" + ], + [ + 16.877, + "ly" + ] + ] + }, + "times": { + "0": 0.4, + "1": 1.549, + "2": 2.7805, + "3": 3.402, + "4": 3.896, + "5": 5.255, + "6": 5.8265, + "7": 6.768, + "8": 8.0845, + "9": 8.706, + "10": 9.56, + "11": 10.954, + "12": 13.638, + "13": 14.697, + "14": 17.6785, + "15": 18.635, + "16": 20.019, + "17": 20.9105 + }, + "end": 22.062 + }, + "name": "cp-line" + }, + "w-s": { + "slice": { + "source": "corpus/s", + "start": 0.0, + "end": 25.34, + "words": "the whole lyric, assembled from corpus", + "dur": 25.34, + "median_f0_hz": 212.8, + "word_f0": [ + { + "t": "sitting", + "start": 0.4, + "end": 1.954, + "f0_hz": 270.3, + "note": "C#4" + }, + { + "t": "curled", + "start": 2.204, + "end": 3.563, + "f0_hz": 217.6, + "note": "A3" + }, + { + "t": "up", + "start": 3.813, + "end": 4.322, + "f0_hz": 203.6, + "note": "G#3" + }, + { + "t": "in", + "start": 4.572, + "end": 5.056, + "f0_hz": 182.8, + "note": "F#3" + }, + { + "t": "myself", + "start": 5.306, + "end": 6.81, + "f0_hz": 209.2, + "note": "G#3" + }, + { + "t": "i", + "start": 7.06, + "end": 7.224, + "f0_hz": 164.0, + "note": "E3" + }, + { + "t": "think", + "start": 7.474, + "end": 8.453, + "f0_hz": 144.4, + "note": "D3" + }, + { + "t": "of", + "start": 8.703, + "end": 9.3395, + "f0_hz": 355.0, + "note": "F4" + }, + { + "t": "a", + "start": 9.5895, + "end": 10.021, + "f0_hz": 358.1, + "note": "F4" + }, + { + "t": "stone", + "start": 10.271, + "end": 12.165, + "f0_hz": 310.9, + "note": "D#4" + }, + { + "t": "just", + "start": 12.415, + "end": 13.449, + "f0_hz": 206.4, + "note": "G#3" + }, + { + "t": "waiting", + "start": 13.699, + "end": 15.6555, + "f0_hz": 218.4, + "note": "A3" + }, + { + "t": "very", + "start": 15.9055, + "end": 16.867, + "f0_hz": 181.8, + "note": "F#3" + }, + { + "t": "patiently", + "start": 17.117, + "end": 19.871, + "f0_hz": 201.0, + "note": "G3" + }, + { + "t": "for", + "start": 20.121, + "end": 20.9125, + "f0_hz": 135.4, + "note": "C#3" + }, + { + "t": "time", + "start": 21.1625, + "end": 22.5615, + "f0_hz": 136.1, + "note": "C#3" + }, + { + "t": "to", + "start": 22.8115, + "end": 24.0255, + "f0_hz": 110.0, + "note": "A2" + }, + { + "t": "pass", + "start": 24.2755, + "end": 25.3395, + "f0_hz": 216.3, + "note": "A3" + } + ] + }, + "align": { + "model": "corpus", + "text": "sitting curled up in myself i think of a stone just waiting very patiently for time to pass", + "words": [ + { + "t": "sitting", + "start": 0.4, + "end": 1.954, + "f0_hz": 270.3, + "note": "C#4" + }, + { + "t": "curled", + "start": 2.204, + "end": 3.563, + "f0_hz": 217.6, + "note": "A3" + }, + { + "t": "up", + "start": 3.813, + "end": 4.322, + "f0_hz": 203.6, + "note": "G#3" + }, + { + "t": "in", + "start": 4.572, + "end": 5.056, + "f0_hz": 182.8, + "note": "F#3" + }, + { + "t": "myself", + "start": 5.306, + "end": 6.81, + "f0_hz": 209.2, + "note": "G#3" + }, + { + "t": "i", + "start": 7.06, + "end": 7.224, + "f0_hz": 164.0, + "note": "E3" + }, + { + "t": "think", + "start": 7.474, + "end": 8.453, + "f0_hz": 144.4, + "note": "D3" + }, + { + "t": "of", + "start": 8.703, + "end": 9.3395, + "f0_hz": 355.0, + "note": "F4" + }, + { + "t": "a", + "start": 9.5895, + "end": 10.021, + "f0_hz": 358.1, + "note": "F4" + }, + { + "t": "stone", + "start": 10.271, + "end": 12.165, + "f0_hz": 310.9, + "note": "D#4" + }, + { + "t": "just", + "start": 12.415, + "end": 13.449, + "f0_hz": 206.4, + "note": "G#3" + }, + { + "t": "waiting", + "start": 13.699, + "end": 15.6555, + "f0_hz": 218.4, + "note": "A3" + }, + { + "t": "very", + "start": 15.9055, + "end": 16.867, + "f0_hz": 181.8, + "note": "F#3" + }, + { + "t": "patiently", + "start": 17.117, + "end": 19.871, + "f0_hz": 201.0, + "note": "G3" + }, + { + "t": "for", + "start": 20.121, + "end": 20.9125, + "f0_hz": 135.4, + "note": "C#3" + }, + { + "t": "time", + "start": 21.1625, + "end": 22.5615, + "f0_hz": 136.1, + "note": "C#3" + }, + { + "t": "to", + "start": 22.8115, + "end": 24.0255, + "f0_hz": 110.0, + "note": "A2" + }, + { + "t": "pass", + "start": 24.2755, + "end": 25.3395, + "f0_hz": 216.3, + "note": "A3" + } + ] + }, + "chart": { + "slice": "s-line", + "beats": 60.0, + "lead": 0.0, + "durs": { + "0": 2.0, + "1": 2.0, + "2": 1.91, + "3": 2.09, + "4": 2.0, + "5": 1.5, + "6": 2.5, + "7": 2.0, + "8": 2.0, + "9": 4.0, + "10": 1.75, + "11": 4.25, + "12": 4.0, + "13": 2.0, + "14": 2.0, + "15": 2.0, + "16": 2.0, + "17": 2.0, + "18": 2.0, + "19": 2.0, + "20": 2.0, + "21": 4.0, + "22": 4.0, + "23": 4.0 + }, + "melody": [ + 7, + 5, + 3, + 2, + 0, + 5, + 2, + -2, + -5, + 12, + 10, + 5, + 2, + 3, + 2, + 0, + -2, + 7, + 5, + 3, + 5, + 7, + 3, + 3 + ], + "sylls": { + "0": [ + [ + null, + "sitting\u00b7a" + ], + [ + 0.665, + "sitting\u00b7b" + ] + ], + "4": [ + [ + null, + "my" + ], + [ + 6.146, + "self" + ] + ], + "11": [ + [ + null, + "wait" + ], + [ + 14.374, + "ing" + ] + ], + "12": [ + [ + null, + "ve" + ], + [ + 16.1305, + "ry" + ] + ], + "13": [ + [ + null, + "pa" + ], + [ + 17.597, + "tient" + ], + [ + 18.377, + "ly" + ] + ] + }, + "times": { + "0": 0.4, + "1": 2.204, + "2": 3.813, + "3": 4.572, + "4": 5.306, + "5": 7.06, + "6": 7.474, + "7": 8.703, + "8": 9.5895, + "9": 10.271, + "10": 12.415, + "11": 13.699, + "12": 15.9055, + "13": 17.117, + "14": 20.121, + "15": 21.1625, + "16": 22.8115, + "17": 24.2755 + }, + "end": 25.3395 + }, + "name": "s-line" + }, + "w-o": { + "slice": { + "source": "corpus/o", + "start": 0.0, + "end": 26.592, + "words": "the whole lyric, assembled from corpus", + "dur": 26.592, + "median_f0_hz": 215.2, + "word_f0": [ + { + "t": "sitting", + "start": 0.4, + "end": 1.7565, + "f0_hz": 265.3, + "note": "C4" + }, + { + "t": "curled", + "start": 2.0065, + "end": 3.148, + "f0_hz": 215.2, + "note": "A3" + }, + { + "t": "up", + "start": 3.398, + "end": 4.1145, + "f0_hz": 201.0, + "note": "G3" + }, + { + "t": "in", + "start": 4.3645, + "end": 4.8785, + "f0_hz": 179.6, + "note": "F3" + }, + { + "t": "myself", + "start": 5.1285, + "end": 6.7175, + "f0_hz": 205.4, + "note": "G#3" + }, + { + "t": "i", + "start": 6.9675, + "end": 7.6165, + "f0_hz": 159.9, + "note": "D#3" + }, + { + "t": "think", + "start": 7.8665, + "end": 8.6755, + "f0_hz": 134.6, + "note": "C3" + }, + { + "t": "of", + "start": 8.9255, + "end": 9.6145, + "f0_hz": 352.5, + "note": "F4" + }, + { + "t": "a", + "start": 9.8645, + "end": 10.2035, + "f0_hz": 351.5, + "note": "F4" + }, + { + "t": "stone", + "start": 10.4535, + "end": 12.1125, + "f0_hz": 309.3, + "note": "D#4" + }, + { + "t": "just", + "start": 12.3625, + "end": 14.464, + "f0_hz": 197.6, + "note": "G3" + }, + { + "t": "waiting", + "start": 14.714, + "end": 16.2505, + "f0_hz": 207.4, + "note": "G#3" + }, + { + "t": "very", + "start": 16.5005, + "end": 18.002, + "f0_hz": 175.5, + "note": "F3" + }, + { + "t": "patiently", + "start": 18.252, + "end": 21.101, + "f0_hz": 241.9, + "note": "B3" + }, + { + "t": "for", + "start": 21.351, + "end": 22.38, + "f0_hz": 270.3, + "note": "C#4" + }, + { + "t": "time", + "start": 22.63, + "end": 23.934, + "f0_hz": 216.2, + "note": "A3" + }, + { + "t": "to", + "start": 24.184, + "end": 24.8555, + "f0_hz": 214.5, + "note": "A3" + }, + { + "t": "pass", + "start": 25.1055, + "end": 26.592, + "f0_hz": 148.7, + "note": "D3" + } + ] + }, + "align": { + "model": "corpus", + "text": "sitting curled up in myself i think of a stone just waiting very patiently for time to pass", + "words": [ + { + "t": "sitting", + "start": 0.4, + "end": 1.7565, + "f0_hz": 265.3, + "note": "C4" + }, + { + "t": "curled", + "start": 2.0065, + "end": 3.148, + "f0_hz": 215.2, + "note": "A3" + }, + { + "t": "up", + "start": 3.398, + "end": 4.1145, + "f0_hz": 201.0, + "note": "G3" + }, + { + "t": "in", + "start": 4.3645, + "end": 4.8785, + "f0_hz": 179.6, + "note": "F3" + }, + { + "t": "myself", + "start": 5.1285, + "end": 6.7175, + "f0_hz": 205.4, + "note": "G#3" + }, + { + "t": "i", + "start": 6.9675, + "end": 7.6165, + "f0_hz": 159.9, + "note": "D#3" + }, + { + "t": "think", + "start": 7.8665, + "end": 8.6755, + "f0_hz": 134.6, + "note": "C3" + }, + { + "t": "of", + "start": 8.9255, + "end": 9.6145, + "f0_hz": 352.5, + "note": "F4" + }, + { + "t": "a", + "start": 9.8645, + "end": 10.2035, + "f0_hz": 351.5, + "note": "F4" + }, + { + "t": "stone", + "start": 10.4535, + "end": 12.1125, + "f0_hz": 309.3, + "note": "D#4" + }, + { + "t": "just", + "start": 12.3625, + "end": 14.464, + "f0_hz": 197.6, + "note": "G3" + }, + { + "t": "waiting", + "start": 14.714, + "end": 16.2505, + "f0_hz": 207.4, + "note": "G#3" + }, + { + "t": "very", + "start": 16.5005, + "end": 18.002, + "f0_hz": 175.5, + "note": "F3" + }, + { + "t": "patiently", + "start": 18.252, + "end": 21.101, + "f0_hz": 241.9, + "note": "B3" + }, + { + "t": "for", + "start": 21.351, + "end": 22.38, + "f0_hz": 270.3, + "note": "C#4" + }, + { + "t": "time", + "start": 22.63, + "end": 23.934, + "f0_hz": 216.2, + "note": "A3" + }, + { + "t": "to", + "start": 24.184, + "end": 24.8555, + "f0_hz": 214.5, + "note": "A3" + }, + { + "t": "pass", + "start": 25.1055, + "end": 26.592, + "f0_hz": 148.7, + "note": "D3" + } + ] + }, + "chart": { + "slice": "o-line", + "beats": 60.0, + "lead": 0.0, + "durs": { + "0": 2.0, + "1": 2.0, + "2": 1.91, + "3": 2.09, + "4": 2.0, + "5": 1.5, + "6": 2.5, + "7": 2.0, + "8": 2.0, + "9": 4.0, + "10": 1.75, + "11": 4.25, + "12": 4.0, + "13": 2.0, + "14": 2.0, + "15": 2.0, + "16": 2.0, + "17": 2.0, + "18": 2.0, + "19": 2.0, + "20": 2.0, + "21": 4.0, + "22": 4.0, + "23": 4.0 + }, + "melody": [ + 7, + 5, + 3, + 2, + 0, + 5, + 2, + -2, + -5, + 12, + 10, + 5, + 2, + 3, + 2, + 0, + -2, + 7, + 5, + 3, + 5, + 7, + 3, + 3 + ], + "sylls": { + "0": [ + [ + null, + "sitting\u00b7a" + ], + [ + 1.445, + "sitting\u00b7b" + ] + ], + "4": [ + [ + null, + "my" + ], + [ + 5.8735, + "self" + ] + ], + "11": [ + [ + null, + "wait" + ], + [ + 15.894, + "ing" + ] + ], + "12": [ + [ + null, + "ve" + ], + [ + 17.6755, + "ry" + ] + ], + "13": [ + [ + null, + "pa" + ], + [ + 20.062, + "tient" + ], + [ + 20.672, + "ly" + ] + ] + }, + "times": { + "0": 0.4, + "1": 2.0065, + "2": 3.398, + "3": 4.3645, + "4": 5.1285, + "5": 6.9675, + "6": 7.8665, + "7": 8.9255, + "8": 9.8645, + "9": 10.4535, + "10": 12.3625, + "11": 14.714, + "12": 16.5005, + "13": 18.252, + "14": 21.351, + "15": 22.63, + "16": 24.184, + "17": 25.1055 + }, + "end": 26.592 + }, + "name": "o-line" + } +} \ No newline at end of file diff --git a/pop/loner/samples/.takes.json b/pop/loner/samples/.takes.json new file mode 100644 --- /dev/null +++ b/pop/loner/samples/.takes.json @@ -0,0 +1,625 @@ +{ + "a": [ + { + "cents": -471, + "dur": 0.8, + "end": 2.42, + "note": "G#3", + "peak_db": -7.1, + "slice": "f-of-a-stone", + "st": 10.29, + "start": 1.62, + "take": "f" + }, + { + "cents": -469, + "dur": 0.8, + "end": 9.82, + "note": "G#3", + "peak_db": -8.0, + "slice": "f-whole-line", + "st": 10.31, + "start": 9.02, + "take": "f" + }, + { + "cents": -521, + "dur": 0.76, + "end": 0.76, + "note": "A#4", + "peak_db": -11.6, + "slice": "n-stone-waiting", + "st": 11.79, + "start": 0.0, + "take": "n" + } + ], + "curled": [ + { + "cents": -524, + "dur": 0.92, + "end": 2.46, + "note": "C#3", + "peak_db": -7.8, + "slice": "f-sitting-curled", + "st": 2.76, + "start": 1.54, + "take": "f" + }, + { + "cents": -523, + "dur": 1.04, + "end": 2.66, + "note": "C#3", + "peak_db": -9.2, + "slice": "f-whole-line", + "st": 2.77, + "start": 1.62, + "take": "f" + }, + { + "cents": -537, + "dur": 0.8, + "end": 1.58, + "note": "C#3", + "peak_db": -9.3, + "slice": "n-getting-curled", + "st": 2.63, + "start": 0.78, + "take": "n" + } + ], + "for": [ + { + "cents": -480, + "dur": 0.62, + "end": 0.62, + "note": "D#3", + "peak_db": -6.5, + "slice": "f-for-time-to-pass", + "st": 5.2, + "start": 0.0, + "take": "f" + }, + { + "cents": -487, + "dur": 1.9, + "end": 19.38, + "note": "C#3", + "peak_db": -7.0, + "slice": "f-whole-line", + "st": 3.13, + "start": 17.48, + "take": "f" + } + ], + "getting": [ + { + "cents": -534, + "dur": 0.78, + "end": 0.78, + "note": "D#3", + "peak_db": -12.9, + "slice": "n-getting-curled", + "st": 4.66, + "start": 0.0, + "take": "n" + } + ], + "i": [ + { + "cents": -501, + "dur": 0.64, + "end": 0.64, + "note": "G#2", + "peak_db": -8.2, + "slice": "f-i-think", + "st": -2.01, + "start": 0.0, + "take": "f" + }, + { + "cents": -501, + "dur": 0.94, + "end": 6.48, + "note": "G#2", + "peak_db": -13.3, + "slice": "f-whole-line", + "st": -2.01, + "start": 5.54, + "take": "f" + }, + { + "cents": -540, + "dur": 0.78, + "end": 4.78, + "note": "G#2", + "peak_db": -7.1, + "slice": "n-getting-curled", + "st": -2.4, + "start": 4.0, + "take": "n" + } + ], + "in": [ + { + "cents": -499, + "dur": 0.72, + "end": 3.86, + "note": "A#3", + "peak_db": -9.5, + "slice": "f-sitting-curled", + "st": 0.01, + "start": 3.14, + "take": "f" + }, + { + "cents": -498, + "dur": 0.8, + "end": 4.16, + "note": "A#3", + "peak_db": -7.4, + "slice": "f-whole-line", + "st": 0.02, + "start": 3.36, + "take": "f" + }, + { + "cents": -496, + "dur": 0.62, + "end": 2.76, + "note": "A#3", + "peak_db": -13.2, + "slice": "n-getting-curled", + "st": 0.04, + "start": 2.14, + "take": "n" + } + ], + "just": [ + { + "cents": -586, + "dur": 1.46, + "end": 1.46, + "note": "C3", + "peak_db": -5.9, + "slice": "f-just-waiting", + "st": 2.14, + "start": 0.0, + "take": "f" + }, + { + "cents": -585, + "dur": 1.265, + "end": 12.6, + "note": "C3", + "peak_db": -8.4, + "slice": "f-whole-line", + "st": 2.15, + "start": 11.335, + "take": "f" + }, + { + "cents": -583, + "dur": 1.88, + "end": 3.94, + "note": "D3", + "peak_db": -10.2, + "slice": "n-stone-waiting", + "st": 4.17, + "start": 2.06, + "take": "n" + } + ], + "myself": [ + { + "cents": -538, + "dur": 1.36, + "end": 5.22, + "note": "D#3", + "peak_db": -6.0, + "slice": "f-sitting-curled", + "st": 4.62, + "start": 3.86, + "take": "f" + }, + { + "cents": -542, + "dur": 1.38, + "end": 5.54, + "note": "D#3", + "peak_db": -9.0, + "slice": "f-whole-line", + "st": 4.58, + "start": 4.16, + "take": "f" + }, + { + "cents": -401, + "dur": 1.24, + "end": 4.0, + "note": "D3", + "peak_db": -6.0, + "slice": "n-getting-curled", + "st": 3.99, + "start": 2.76, + "take": "n" + } + ], + "of": [ + { + "cents": -511, + "dur": 1.62, + "end": 1.62, + "note": "A#4", + "peak_db": -6.4, + "slice": "f-of-a-stone", + "st": 11.89, + "start": 0.0, + "take": "f" + }, + { + "cents": -513, + "dur": 1.94, + "end": 9.02, + "note": "A#4", + "peak_db": -7.4, + "slice": "f-whole-line", + "st": 11.87, + "start": 7.08, + "take": "f" + } + ], + "pass": [ + { + "cents": -499, + "dur": 1.86, + "end": 5.7, + "note": "C#3", + "peak_db": -8.2, + "slice": "f-for-time-to-pass", + "st": 3.01, + "start": 3.84, + "take": "f" + }, + { + "cents": -498, + "dur": 1.56, + "end": 24.42, + "note": "C#3", + "peak_db": -8.7, + "slice": "f-whole-line", + "st": 3.02, + "start": 22.86, + "take": "f" + }, + { + "cents": -524, + "dur": 0.92, + "end": 3.56, + "note": "C#3", + "peak_db": -5.9, + "slice": "n-for-time-to-pass", + "st": 2.76, + "start": 2.64, + "take": "n" + } + ], + "patiently": [ + { + "cents": -490, + "dur": 1.52, + "end": 2.92, + "note": "F3", + "peak_db": -5.3, + "slice": "f-very-patiently", + "st": 7.1, + "start": 1.4, + "take": "f" + }, + { + "cents": -490, + "dur": 1.3, + "end": 17.48, + "note": "F3", + "peak_db": -5.3, + "slice": "f-whole-line", + "st": 7.1, + "start": 16.18, + "take": "f" + }, + { + "cents": -580, + "dur": 1.18, + "end": 8.04, + "note": "E3", + "peak_db": -5.7, + "slice": "n-stone-waiting", + "st": 6.2, + "start": 6.86, + "take": "n" + } + ], + "sitting": [ + { + "cents": -570, + "dur": 1.54, + "end": 1.54, + "note": "E3", + "peak_db": -5.2, + "slice": "f-sitting-curled", + "st": 6.3, + "start": 0.0, + "take": "f" + }, + { + "cents": -531, + "dur": 1.4, + "end": 1.62, + "note": "F3", + "peak_db": -6.6, + "slice": "f-whole-line", + "st": 6.69, + "start": 0.22, + "take": "f" + } + ], + "stone": [ + { + "cents": -497, + "dur": 0.74, + "end": 3.16, + "note": "D#3", + "peak_db": -7.6, + "slice": "f-of-a-stone", + "st": 5.03, + "start": 2.42, + "take": "f" + }, + { + "cents": -494, + "dur": 0.88, + "end": 10.7, + "note": "D#3", + "peak_db": -8.5, + "slice": "f-whole-line", + "st": 5.06, + "start": 9.82, + "take": "f" + }, + { + "cents": -595, + "dur": 1.3, + "end": 2.06, + "note": "G3", + "peak_db": -4.5, + "slice": "n-stone-waiting", + "st": 9.05, + "start": 0.76, + "take": "n" + } + ], + "the": [ + { + "cents": -533, + "dur": 0.16, + "end": 0.16, + "note": "D#3", + "peak_db": -8.8, + "slice": "n-for-time-to-pass", + "st": 4.67, + "start": 0.0, + "take": "n" + } + ], + "think": [ + { + "cents": -477, + "dur": 0.68, + "end": 1.32, + "note": "F2", + "peak_db": -10.5, + "slice": "f-i-think", + "st": -4.77, + "start": 0.64, + "take": "f" + }, + { + "cents": -490, + "dur": 0.6, + "end": 7.08, + "note": "F2", + "peak_db": -15.6, + "slice": "f-whole-line", + "st": -4.9, + "start": 6.48, + "take": "f" + }, + { + "cents": -537, + "dur": 0.32, + "end": 5.1, + "note": "F2", + "peak_db": -14.0, + "slice": "n-getting-curled", + "st": -5.37, + "start": 4.78, + "take": "n" + } + ], + "time": [ + { + "cents": -489, + "dur": 1.44, + "end": 2.06, + "note": "F3", + "peak_db": -7.4, + "slice": "f-for-time-to-pass", + "st": 7.11, + "start": 0.62, + "take": "f" + }, + { + "cents": -488, + "dur": 1.34, + "end": 20.72, + "note": "F3", + "peak_db": -7.9, + "slice": "f-whole-line", + "st": 7.12, + "start": 19.38, + "take": "f" + }, + { + "cents": -528, + "dur": 0.94, + "end": 1.1, + "note": "F3", + "peak_db": -7.9, + "slice": "n-for-time-to-pass", + "st": 6.72, + "start": 0.16, + "take": "n" + } + ], + "to": [ + { + "cents": -496, + "dur": 1.78, + "end": 3.84, + "note": "C#3", + "peak_db": -11.5, + "slice": "f-for-time-to-pass", + "st": 3.04, + "start": 2.06, + "take": "f" + }, + { + "cents": -496, + "dur": 2.14, + "end": 22.86, + "note": "C#3", + "peak_db": -12.0, + "slice": "f-whole-line", + "st": 3.04, + "start": 20.72, + "take": "f" + }, + { + "cents": -539, + "dur": 1.54, + "end": 2.64, + "note": "C#3", + "peak_db": -8.9, + "slice": "n-for-time-to-pass", + "st": 2.61, + "start": 1.1, + "take": "n" + } + ], + "up": [ + { + "cents": -506, + "dur": 0.68, + "end": 3.14, + "note": "C3", + "peak_db": -8.5, + "slice": "f-sitting-curled", + "st": 1.94, + "start": 2.46, + "take": "f" + }, + { + "cents": -504, + "dur": 0.7, + "end": 3.36, + "note": "C3", + "peak_db": -10.0, + "slice": "f-whole-line", + "st": 1.96, + "start": 2.66, + "take": "f" + }, + { + "cents": -526, + "dur": 0.56, + "end": 2.14, + "note": "C3", + "peak_db": -12.9, + "slice": "n-getting-curled", + "st": 1.74, + "start": 1.58, + "take": "n" + } + ], + "very": [ + { + "cents": -505, + "dur": 1.4, + "end": 1.4, + "note": "A#3", + "peak_db": -10.2, + "slice": "f-very-patiently", + "st": -0.05, + "start": 0.0, + "take": "f" + }, + { + "cents": -498, + "dur": 1.92, + "end": 16.18, + "note": "A#3", + "peak_db": -10.2, + "slice": "f-whole-line", + "st": 0.02, + "start": 14.26, + "take": "f" + }, + { + "cents": -541, + "dur": 1.44, + "end": 6.86, + "note": "A#3", + "peak_db": -10.3, + "slice": "n-stone-waiting", + "st": -0.41, + "start": 5.42, + "take": "n" + } + ], + "waiting": [ + { + "cents": -510, + "dur": 1.48, + "end": 2.94, + "note": "C#3", + "peak_db": -5.4, + "slice": "f-just-waiting", + "st": 2.9, + "start": 1.46, + "take": "f" + }, + { + "cents": -511, + "dur": 1.66, + "end": 14.26, + "note": "C#3", + "peak_db": -7.9, + "slice": "f-whole-line", + "st": 2.89, + "start": 12.6, + "take": "f" + }, + { + "cents": -513, + "dur": 1.48, + "end": 5.42, + "note": "C#3", + "peak_db": -5.7, + "slice": "n-stone-waiting", + "st": 2.87, + "start": 3.94, + "take": "n" + } + ] +} \ No newline at end of file diff --git a/pop/loner/vox-dub/.carrier-da.mp3 b/pop/loner/vox-dub/.carrier-da.mp3 new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/.carrier-da.mp3 diff --git a/pop/loner/vox-dub/.carrier-es.mp3 b/pop/loner/vox-dub/.carrier-es.mp3 new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/.carrier-es.mp3 diff --git a/pop/loner/vox-dub/.carrier-fr.mp3 b/pop/loner/vox-dub/.carrier-fr.mp3 new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/.carrier-fr.mp3 diff --git a/pop/loner/vox-dub/.carrier-hi.mp3 b/pop/loner/vox-dub/.carrier-hi.mp3 new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/.carrier-hi.mp3 diff --git a/pop/loner/vox-dub/.carrier-ru.mp3 b/pop/loner/vox-dub/.carrier-ru.mp3 new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/.carrier-ru.mp3 diff --git a/pop/loner/vox-dub/.dub.json b/pop/loner/vox-dub/.dub.json new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/.dub.json @@ -0,0 +1,29 @@ +{ + "da": { + "consent": "Camille Klein (@cksuperstore), via @jeffrey", + "dubbing_id": "RGpvxSGiNvpqkm40Ivcn", + "engine": "elevenlabs/dubbing", + "language": "Danish", + "note": "SYNTHETIC VOICE \u2014 her voice model singing a translation; not a take she performed. Label on any release.", + "source": "samples/f-whole-line.wav", + "synthetic": true + }, + "es": { + "consent": "Camille Klein (@cksuperstore), via @jeffrey", + "dubbing_id": "hvb44SHj5ZVljGDuzQGY", + "engine": "elevenlabs/dubbing", + "language": "Spanish", + "note": "SYNTHETIC VOICE \u2014 her voice model singing a translation; not a take she performed. Label on any release.", + "source": "samples/f-whole-line.wav", + "synthetic": true + }, + "fr": { + "consent": "Camille Klein (@cksuperstore), via @jeffrey", + "dubbing_id": "XoHEYSdVJyHdfciUMNSH", + "engine": "elevenlabs/dubbing", + "language": "French", + "note": "SYNTHETIC VOICE \u2014 her voice model singing a translation; not a take she performed. Label on any release.", + "source": "samples/f-whole-line.wav", + "synthetic": true + } +} \ No newline at end of file diff --git a/pop/loner/vox-dub/.voice.json b/pop/loner/vox-dub/.voice.json new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/.voice.json @@ -0,0 +1,26 @@ +{ + "voice_id": "UzFG8DoU8szypvfbc4Rl", + "name": "Camille Klein \u00b7 loner IVC (consented)", + "sources": [ + "6955972523087416582.mp3", + "6974224412614675718.mp3", + "6988954628167585030.mp3", + "6994920700746206470.mp3", + "6996714516234947845.mp3", + "7021262898479549702.mp3", + "7076361738786213166.mp3", + "7100768279983181099.mp3", + "7108062006980201771.mp3", + "7168612922757877035.mp3", + "7168939549962308906.mp3", + "7173130377798716714.mp3", + "7226114462145695018.mp3", + "7226226683349798190.mp3", + "7226527805008268586.mp3", + "7230893600219942186.mp3", + "7233760335990230315.mp3", + "7233886426910330158.mp3" + ], + "synthetic": true, + "consent": "Camille Klein (@cksuperstore), via @jeffrey 2026-08-19" +} \ No newline at end of file diff --git a/pop/loner/vox-dub/.words.json b/pop/loner/vox-dub/.words.json new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/.words.json @@ -0,0 +1,681 @@ +{ + "fr": [ + { + "t": "Assise", + "start": 0.079, + "end": 0.5 + }, + { + "t": "recroquevillée", + "start": 0.56, + "end": 1.179 + }, + { + "t": "en", + "start": 1.22, + "end": 1.279 + }, + { + "t": "moi-même,", + "start": 1.319, + "end": 1.719 + }, + { + "t": "je", + "start": 2.379, + "end": 2.5 + }, + { + "t": "pense", + "start": 2.539, + "end": 2.759 + }, + { + "t": "à", + "start": 2.819, + "end": 2.839 + }, + { + "t": "une", + "start": 2.899, + "end": 3.019 + }, + { + "t": "pierre", + "start": 3.059, + "end": 3.439 + }, + { + "t": "qui", + "start": 3.959, + "end": 4.059 + }, + { + "t": "attend", + "start": 4.119, + "end": 4.42 + }, + { + "t": "très", + "start": 4.46, + "end": 4.639 + }, + { + "t": "patiemment", + "start": 4.699, + "end": 5.179 + }, + { + "t": "que", + "start": 5.239, + "end": 5.279 + }, + { + "t": "le", + "start": 5.339, + "end": 5.38 + }, + { + "t": "temps", + "start": 5.46, + "end": 5.639 + }, + { + "t": "passe", + "start": 5.699, + "end": 6.039 + } + ], + "es": [ + { + "t": "Sentada", + "start": 0.119, + "end": 0.56 + }, + { + "t": "acurrucada", + "start": 0.579, + "end": 1.159 + }, + { + "t": "en", + "start": 1.179, + "end": 1.259 + }, + { + "t": "mí", + "start": 1.279, + "end": 1.379 + }, + { + "t": "misma,", + "start": 1.419, + "end": 1.759 + }, + { + "t": "pienso", + "start": 2.259, + "end": 2.559 + }, + { + "t": "en", + "start": 2.599, + "end": 2.659 + }, + { + "t": "una", + "start": 2.7, + "end": 2.799 + }, + { + "t": "piedra", + "start": 2.899, + "end": 3.259 + }, + { + "t": "que", + "start": 3.879, + "end": 3.98 + }, + { + "t": "espera", + "start": 4.059, + "end": 4.439 + }, + { + "t": "muy", + "start": 4.48, + "end": 4.579 + }, + { + "t": "pacientemente", + "start": 4.659, + "end": 5.38 + }, + { + "t": "a", + "start": 5.42, + "end": 5.46 + }, + { + "t": "que", + "start": 5.539, + "end": 5.579 + }, + { + "t": "pase", + "start": 5.679, + "end": 5.899 + }, + { + "t": "el", + "start": 5.92, + "end": 6.019 + }, + { + "t": "tiempo", + "start": 6.059, + "end": 6.439 + } + ], + "da": [ + { + "t": "Jeg", + "start": 0.079, + "end": 0.159 + }, + { + "t": "sidder", + "start": 0.239, + "end": 0.459 + }, + { + "t": "krøllet", + "start": 0.519, + "end": 0.819 + }, + { + "t": "sammen", + "start": 0.859, + "end": 1.1 + }, + { + "t": "i", + "start": 1.139, + "end": 1.179 + }, + { + "t": "mig", + "start": 1.22, + "end": 1.36 + }, + { + "t": "selv.", + "start": 1.399, + "end": 1.639 + }, + { + "t": "Jeg", + "start": 2.159, + "end": 2.259 + }, + { + "t": "tænker", + "start": 2.299, + "end": 2.539 + }, + { + "t": "på", + "start": 2.579, + "end": 2.639 + }, + { + "t": "en", + "start": 2.659, + "end": 2.759 + }, + { + "t": "sten,", + "start": 2.799, + "end": 3.079 + }, + { + "t": "der", + "start": 3.24, + "end": 3.319 + }, + { + "t": "bare", + "start": 3.359, + "end": 3.46 + }, + { + "t": "venter", + "start": 3.519, + "end": 3.779 + }, + { + "t": "meget", + "start": 3.819, + "end": 3.979 + }, + { + "t": "tålmodigt", + "start": 4.039, + "end": 4.5 + }, + { + "t": "på,", + "start": 4.559, + "end": 4.679 + }, + { + "t": "at", + "start": 4.92, + "end": 5.0 + }, + { + "t": "tiden", + "start": 5.079, + "end": 5.299 + }, + { + "t": "går", + "start": 5.339, + "end": 5.559 + } + ], + "ru": [ + { + "t": "Сижу,", + "start": 0.119, + "end": 0.5 + }, + { + "t": "свернувшись", + "start": 0.659, + "end": 1.24 + }, + { + "t": "в", + "start": 1.279, + "end": 1.339 + }, + { + "t": "себе.", + "start": 1.399, + "end": 1.679 + }, + { + "t": "Я", + "start": 2.22, + "end": 2.259 + }, + { + "t": "думаю", + "start": 2.339, + "end": 2.559 + }, + { + "t": "о", + "start": 2.599, + "end": 2.7 + }, + { + "t": "камне,", + "start": 2.759, + "end": 3.099 + }, + { + "t": "который", + "start": 3.279, + "end": 3.599 + }, + { + "t": "очень", + "start": 3.679, + "end": 3.899 + }, + { + "t": "терпеливо", + "start": 3.939, + "end": 4.38 + }, + { + "t": "ждет,", + "start": 4.42, + "end": 4.699 + }, + { + "t": "пока", + "start": 4.859, + "end": 5.039 + }, + { + "t": "пройдет", + "start": 5.119, + "end": 5.42 + }, + { + "t": "время", + "start": 5.46, + "end": 5.779 + } + ], + "hi": [ + { + "t": "अपने", + "start": 0.059, + "end": 0.319 + }, + { + "t": "भीतर", + "start": 0.359, + "end": 0.699 + }, + { + "t": "सिमटी", + "start": 0.74, + "end": 1.019 + }, + { + "t": "हुई", + "start": 1.079, + "end": 1.199 + }, + { + "t": "बैठी", + "start": 1.24, + "end": 1.459 + }, + { + "t": "हूँ।", + "start": 1.539, + "end": 2.22 + }, + { + "t": "मैं", + "start": 2.259, + "end": 2.359 + }, + { + "t": "एक", + "start": 2.399, + "end": 2.539 + }, + { + "t": "पत्थर", + "start": 2.579, + "end": 2.819 + }, + { + "t": "के", + "start": 2.879, + "end": 2.98 + }, + { + "t": "बारे", + "start": 3.019, + "end": 3.199 + }, + { + "t": "में", + "start": 3.22, + "end": 3.339 + }, + { + "t": "सोचती", + "start": 3.359, + "end": 3.659 + }, + { + "t": "हूँ", + "start": 3.72, + "end": 3.819 + }, + { + "t": "जो", + "start": 4.46, + "end": 4.559 + }, + { + "t": "बहुत", + "start": 4.599, + "end": 4.839 + }, + { + "t": "धीरज", + "start": 4.88, + "end": 5.179 + }, + { + "t": "से", + "start": 5.239, + "end": 5.359 + }, + { + "t": "समय", + "start": 5.4, + "end": 5.619 + }, + { + "t": "के", + "start": 5.659, + "end": 5.759 + }, + { + "t": "बीतने", + "start": 5.799, + "end": 6.079 + }, + { + "t": "का", + "start": 6.139, + "end": 6.179 + }, + { + "t": "इंतजार", + "start": 6.239, + "end": 6.599 + }, + { + "t": "कर", + "start": 6.639, + "end": 6.739 + }, + { + "t": "रहा", + "start": 6.779, + "end": 6.94 + }, + { + "t": "है।", + "start": 7.0, + "end": 7.179 + } + ], + "s-whole-line": [ + { + "t": "Sitting", + "start": 0.439, + "end": 1.719 + }, + { + "t": "curled", + "start": 1.939, + "end": 2.72 + }, + { + "t": "up", + "start": 2.819, + "end": 3.359 + }, + { + "t": "in", + "start": 3.439, + "end": 3.859 + }, + { + "t": "myself,", + "start": 4.039, + "end": 5.239 + }, + { + "t": "I", + "start": 5.519, + "end": 5.759 + }, + { + "t": "think", + "start": 5.94, + "end": 6.279 + }, + { + "t": "of", + "start": 6.699, + "end": 7.899 + }, + { + "t": "a", + "start": 8.099, + "end": 8.3 + }, + { + "t": "stone", + "start": 8.5, + "end": 9.22 + }, + { + "t": "just", + "start": 9.96, + "end": 10.679 + }, + { + "t": "waiting", + "start": 11.259, + "end": 12.46 + }, + { + "t": "very", + "start": 12.619, + "end": 13.479 + }, + { + "t": "patiently", + "start": 13.88, + "end": 15.699 + }, + { + "t": "for", + "start": 15.899, + "end": 16.379 + }, + { + "t": "time", + "start": 16.6, + "end": 17.319 + }, + { + "t": "to", + "start": 17.859, + "end": 18.52 + }, + { + "t": "pass", + "start": 19.119, + "end": 20.159 + } + ], + "o-whole-line": [ + { + "t": "Sitting", + "start": 0.14, + "end": 1.459 + }, + { + "t": "curled", + "start": 1.639, + "end": 2.46 + }, + { + "t": "up", + "start": 2.599, + "end": 3.119 + }, + { + "t": "in", + "start": 3.259, + "end": 3.539 + }, + { + "t": "myself,", + "start": 3.819, + "end": 5.119 + }, + { + "t": "I", + "start": 5.299, + "end": 5.619 + }, + { + "t": "think", + "start": 5.819, + "end": 6.259 + }, + { + "t": "of", + "start": 6.599, + "end": 7.899 + }, + { + "t": "a", + "start": 8.0, + "end": 8.239 + }, + { + "t": "stone", + "start": 8.479, + "end": 9.22 + }, + { + "t": "just", + "start": 9.96, + "end": 10.699 + }, + { + "t": "waiting", + "start": 11.319, + "end": 12.559 + }, + { + "t": "very", + "start": 12.719, + "end": 13.579 + }, + { + "t": "patiently", + "start": 13.96, + "end": 15.779 + }, + { + "t": "for", + "start": 16.0, + "end": 16.42 + }, + { + "t": "time", + "start": 16.659, + "end": 17.42 + }, + { + "t": "to", + "start": 17.94, + "end": 18.52 + }, + { + "t": "pass", + "start": 19.079, + "end": 20.339 + } + ] +} \ No newline at end of file diff --git a/pop/loner/vox-dub/spoken-da.mp3 b/pop/loner/vox-dub/spoken-da.mp3 new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/spoken-da.mp3 diff --git a/pop/loner/vox-dub/spoken-es.mp3 b/pop/loner/vox-dub/spoken-es.mp3 new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/spoken-es.mp3 diff --git a/pop/loner/vox-dub/spoken-fr.mp3 b/pop/loner/vox-dub/spoken-fr.mp3 new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/spoken-fr.mp3 diff --git a/pop/loner/vox-dub/sts-da.mp3 b/pop/loner/vox-dub/sts-da.mp3 new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/sts-da.mp3 diff --git a/pop/loner/vox-dub/sts-es.mp3 b/pop/loner/vox-dub/sts-es.mp3 new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/sts-es.mp3 diff --git a/pop/loner/vox-dub/sts-fr.mp3 b/pop/loner/vox-dub/sts-fr.mp3 new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/sts-fr.mp3 diff --git a/pop/loner/vox-dub/sts-hi.mp3 b/pop/loner/vox-dub/sts-hi.mp3 new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/sts-hi.mp3 diff --git a/pop/loner/vox-dub/sts-ru.mp3 b/pop/loner/vox-dub/sts-ru.mp3 new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/sts-ru.mp3 diff --git a/pop/loner/vox-dub/whole-line-dub-da.mp3 b/pop/loner/vox-dub/whole-line-dub-da.mp3 new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/whole-line-dub-da.mp3 diff --git a/pop/loner/vox-dub/whole-line-dub-es.mp3 b/pop/loner/vox-dub/whole-line-dub-es.mp3 new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/whole-line-dub-es.mp3 diff --git a/pop/loner/vox-dub/whole-line-dub-fr.mp3 b/pop/loner/vox-dub/whole-line-dub-fr.mp3 new file mode 100644 --- /dev/null +++ b/pop/loner/vox-dub/whole-line-dub-fr.mp3 diff --git a/pop/loner/vox4/.chart.json b/pop/loner/vox4/.chart.json --- a/pop/loner/vox4/.chart.json +++ b/pop/loner/vox4/.chart.json @@ -1,59 +1,67 @@ { "w-whole-line": { - "leadIn": 0.04, - "beats": 59.0, + "leadIn": 0.33, + "beats": 60.0, "voiced": [ [ - -0.0407, + -0.183, 7.9605 ], [ 8.0012, - 11.5087 + 12.139 ], [ - 11.529, - 12.9218 + 12.1695, + 13.8978 ], [ - 12.9523, - 16.8258 + 13.9385, + 17.8222 ], [ - 16.9885, - 23.607 + 17.9848, + 23.8002 ], [ - 23.9527, - 30.8558 + 23.8307, + 24.4813 ], [ - 30.9575, - 38.6537 + 24.5322, + 27.5923 ], [ - 38.7655, - 40.87 + 27.816, + 31.8522 ], [ - 40.9412, - 42.8932 + 31.964, + 39.6093 ], [ - 42.9847, - 45.9432 + 39.833, + 42.4052 ], [ - 45.9838, - 47.824 + 42.4458, + 43.6557 ], [ - 47.8647, - 55.5913 + 43.6963, + 45.9635 ], [ - 55.7743, - 59.8105 + 45.994, + 48.2205 + ], + [ + 48.2815, + 55.4795 + ], + [ + 55.815, + 59.8715 ] ], "notes": [ @@ -62,177 +70,205 @@ "beat": 0.0, "dur": 2.0, "st": 7, "t": "sitting\u00b7a", - "lead": 0.0813 + "lead": 0.671, + "w": 0 }, { "beat": 2.0, "dur": 2.0, "st": 5, "t": "sitting\u00b7b", - "lead": 0.0 + "lead": 0.0, + "w": 0 }, { "beat": 4.0, "dur": 1.91, "st": 3, "t": "curled", - "lead": 0.0 + "lead": 0.0, + "w": 1 }, { "beat": 5.91, "dur": 2.09, "st": 2, "t": "up", - "lead": 0.0 + "lead": 0.0, + "w": 2 }, { "beat": 8.0, - "dur": 1.5, + "dur": 2.0, "st": 0, "t": "in", - "lead": 0.0 + "lead": 0.0, + "w": 3 }, { - "beat": 9.5, + "beat": 10.0, "dur": 1.5, "st": 5, "t": "my", - "lead": 0.0 + "lead": 0.0, + "w": 4 }, { - "beat": 11.0, - "dur": 2.0, + "beat": 11.5, + "dur": 2.5, "st": 2, "t": "self", - "lead": 0.0 + "lead": 0.0, + "w": 4 }, { - "beat": 13.0, + "beat": 14.0, "dur": 2.0, "st": -2, "t": "i", - "lead": 0.0 + "lead": 0.0, + "w": 5 }, { - "beat": 15.0, + "beat": 16.0, "dur": 2.0, "st": -5, "t": "think", - "lead": 0.0 + "lead": 0.0, + "w": 6 }, { - "beat": 17.0, + "beat": 18.0, "dur": 4.0, "st": 12, "t": "of", - "lead": 0.0203 + "lead": 0.0203, + "w": 7 }, { - "beat": 21.0, - "dur": 3.0, + "beat": 22.0, + "dur": 1.75, "st": 10, "t": "a", - "lead": 0.0 + "lead": 0.0, + "w": 8 }, { - "beat": 24.0, - "dur": 3.0, + "beat": 23.75, + "dur": 4.25, "st": 5, "t": "stone", - "lead": 0.1017 + "lead": 0.0, + "w": 9 }, { - "beat": 27.0, + "beat": 28.0, "dur": 4.0, "st": 2, "t": "just", - "lead": 0.0 + "lead": 0.4067, + "w": 10 }, { - "beat": 31.0, + "beat": 32.0, "dur": 2.0, "st": 3, "t": "wait", - "lead": 0.0813 + "lead": 0.0813, + "w": 11 }, { - "beat": 33.0, + "beat": 34.0, "dur": 2.0, "st": 2, "t": "ing", - "lead": 0.0 + "lead": 0.0, + "w": 11 }, { - "beat": 35.0, + "beat": 36.0, "dur": 2.0, "st": 0, "t": "ve", - "lead": 0.0 + "lead": 0.0, + "w": 12 }, { - "beat": 37.0, + "beat": 38.0, "dur": 2.0, "st": -2, "t": "ry", - "lead": 0.0 + "lead": 0.0, + "w": 12 }, { - "beat": 39.0, + "beat": 40.0, "dur": 2.0, "st": 7, "t": "pa", - "lead": 0.0 + "lead": 0.3253, + "w": 13 }, { - "beat": 41.0, - "dur": 2.5, + "beat": 42.0, + "dur": 2.0, "st": 5, "t": "tient", - "lead": 0.122 + "lead": 0.0, + "w": 13 }, { - "beat": 43.5, - "dur": 2.5, + "beat": 44.0, + "dur": 2.0, "st": 3, "t": "ly", - "lead": 0.0 + "lead": 0.0, + "w": 13 }, { "beat": 46.0, "dur": 2.0, "st": 5, "t": "for", - "lead": 0.0 + "lead": 0.0, + "w": 14 }, { "beat": 48.0, "dur": 4.0, "st": 7, "t": "time", - "lead": 0.0 + "lead": 0.0, + "w": 15 }, { "beat": 52.0, "dur": 4.0, "st": 3, "t": "to", - "lead": 0.0 + "lead": 0.0, + "w": 16 }, { "beat": 56.0, - "dur": 3.0, + "dur": 4.0, "st": 3, "t": "pass", - "lead": 0.0 + "lead": 0.5185, + "w": 17 } ] }, "w-sitting-curled": { - "leadIn": 0.02, + "leadIn": 0.04, "beats": 11.0, "voiced": [ [ - 0.0, + -0.0407, + 6.466 + ], + [ + 6.4965, 9.8617 ], [ @@ -250,44 +286,49 @@ "beat": 0.0, "dur": 3.0, "st": 6, "t": "Sitting", - "lead": 0.0407 + "lead": 0.0813, + "w": 0 }, { "beat": 3.0, "dur": 2.0, "st": 3, "t": "curled", - "lead": 0.0 + "lead": 0.0, + "w": 1 }, { "beat": 5.0, "dur": 1.5, "st": 2, "t": "up", - "lead": 0.0 + "lead": 0.0, + "w": 2 }, { "beat": 6.5, "dur": 1.5, "st": 0, "t": "in", - "lead": 0.0 + "lead": 0.0, + "w": 3 }, { "beat": 8.0, "dur": 3.0, "st": 5, "t": "myself", - "lead": 0.0 + "lead": 0.0, + "w": 4 } ] }, "w-i-think": { - "leadIn": 0.02, + "leadIn": 0.04, "beats": 3.5, "voiced": [ [ - 0.0, + -0.0407, 3.4567 ], [ @@ -305,14 +346,16 @@ "beat": 0.0, "dur": 2.0, "st": -2, "t": "I", - "lead": 0.0407 + "lead": 0.0813, + "w": 0 }, { "beat": 2.0, "dur": 1.5, "st": -5, "t": "think", - "lead": 0.0 + "lead": 0.0, + "w": 1 } ] }, @@ -322,10 +365,10 @@ "beats": 8.0, "voiced": [ [ 0.0, - 5.8052 + 5.7645 ], [ - 5.9983, + 5.9475, 8.3265 ] ], @@ -335,31 +378,34 @@ "beat": 0.0, "dur": 4.0, "st": 12, "t": "of", - "lead": 0.0 + "lead": 0.0, + "w": 0 }, { "beat": 4.0, "dur": 2.0, "st": 10, "t": "a", - "lead": 0.0 + "lead": 0.0, + "w": 1 }, { "beat": 6.0, "dur": 2.0, "st": 5, "t": "stone", - "lead": 0.0508 + "lead": 0.1017, + "w": 2 } ] }, "w-just-waiting": { - "leadIn": 0.075, + "leadIn": 0.15, "beats": 6.5, "voiced": [ [ - 0.0, - 3.3855 + -0.1525, + 3.3652 ], [ 3.4973, @@ -372,14 +418,16 @@ "beat": 0.0, "dur": 3.5, "st": 2, "t": "Just", - "lead": 0.1525 + "lead": 0.305, + "w": 0 }, { "beat": 3.5, "dur": 3.0, "st": 3, "t": "waiting", - "lead": 0.0 + "lead": 0.0, + "w": 1 } ] }, @@ -389,10 +437,14 @@ "beats": 8.5, "voiced": [ [ 0.0, - 7.3912 + 4.636 ], [ - 7.4217, + 4.7377, + 7.3607 + ], + [ + 7.4013, 8.4993 ], [ @@ -410,27 +462,29 @@ "beat": 0.0, "dur": 5.0, "st": 0, "t": "very", - "lead": 0.0 + "lead": 0.0, + "w": 0 }, { "beat": 5.0, "dur": 3.5, "st": 7, "t": "patiently", - "lead": 0.0 + "lead": 0.0, + "w": 1 } ] }, "w-for-time-to-pass": { - "leadIn": 0.035, + "leadIn": 0.07, "beats": 12.5, "voiced": [ [ - 0.0, - 1.8605 + -0.0712, + 1.7385 ], [ - 2.0028, + 1.8808, 4.4937 ], [ @@ -448,28 +502,32 @@ "beat": 0.0, "dur": 2.0, "st": 5, "t": "for", - "lead": 0.0712 + "lead": 0.1423, + "w": 0 }, { "beat": 2.0, "dur": 2.5, "st": 7, "t": "time", - "lead": 0.122 + "lead": 0.244, + "w": 1 }, { "beat": 4.5, "dur": 4.0, "st": 3, "t": "to", - "lead": 0.0 + "lead": 0.0, + "w": 2 }, { "beat": 8.5, "dur": 4.0, "st": 3, "t": "pass", - "lead": 0.0 + "lead": 0.0, + "w": 3 } ] }, @@ -494,7 +552,11 @@ 7.4623, 8.5095 ], [ - 8.5298, + 8.5197, + 10.3903 + ], + [ + 10.4005, 11.1427 ] ], @@ -504,49 +566,56 @@ "beat": 0.0, "dur": 1.5, "st": 5, "t": "getting", - "lead": 0.0 + "lead": 0.0, + "w": 0 }, { "beat": 1.5, "dur": 2.5, "st": 3, "t": "curled", - "lead": 0.0 + "lead": 0.0, + "w": 1 }, { "beat": 4.0, "dur": 0.5, "st": 1, "t": "up", - "lead": 0.0 + "lead": 0.0, + "w": 2 }, { "beat": 4.5, "dur": 1.5, "st": 0, "t": "in", - "lead": 0.0 + "lead": 0.0, + "w": 3 }, { "beat": 6.0, "dur": 2.5, "st": 4, "t": "myself", - "lead": 0.0 + "lead": 0.0, + "w": 4 }, { "beat": 8.5, "dur": 2.0, "st": -2, "t": "i", - "lead": 0.0 + "lead": 0.0, + "w": 5 }, { "beat": 10.5, "dur": 0.5, "st": -5, "t": "think", - "lead": 0.0 + "lead": 0.0, + "w": 6 } ] }, @@ -556,18 +625,26 @@ "beats": 17.0, "voiced": [ [ 0.0, - 3.3042 + 1.8808 ], [ - 3.4363, - 8.0012 + 1.9012, + 3.2635 ], [ - 8.0622, - 16.3073 + 3.4058, + 7.9605 + ], + [ + 8.052, + 14.8433 + ], + [ + 14.8738, + 16.2972 ], [ - 16.3378, + 16.3277, 17.3443 ] ], @@ -577,42 +654,48 @@ "beat": 0.0, "dur": 2.0, "st": 12, "t": "A", - "lead": 0.0 + "lead": 0.0, + "w": 0 }, { "beat": 2.0, "dur": 2.0, "st": 9, "t": "stone", - "lead": 0.0 + "lead": 0.0, + "w": 1 }, { "beat": 4.0, "dur": 4.0, "st": 5, "t": "just", - "lead": 0.0 + "lead": 0.0, + "w": 2 }, { "beat": 8.0, "dur": 4.0, "st": 3, "t": "waiting", - "lead": 0.0 + "lead": 0.0, + "w": 3 }, { "beat": 12.0, "dur": 3.0, "st": 0, "t": "very", - "lead": 0.0 + "lead": 0.0, + "w": 4 }, { "beat": 15.0, "dur": 2.0, "st": 6, "t": "patiently", - "lead": 0.0 + "lead": 0.0, + "w": 5 } ] }, @@ -643,28 +726,2624 @@ "beat": 0.0, "dur": 0.5, "st": 5, "t": "the", - "lead": 0.0 + "lead": 0.0, + "w": 0 }, { "beat": 0.5, "dur": 1.0, "st": 7, "t": "time", - "lead": 0.0 + "lead": 0.0, + "w": 1 }, { "beat": 1.5, "dur": 2.5, "st": 3, "t": "to", - "lead": 0.0 + "lead": 0.0, + "w": 2 + }, + { + "beat": 4.0, + "dur": 1.5, + "st": 3, + "t": "pass", + "lead": 0.0, + "w": 3 + } + ] + }, + "w-rq": { + "leadIn": 0.43, + "beats": 60.0, + "voiced": [ + [ + -0.061, + 3.9142 + ], + [ + 3.9752, + 5.7848 + ], + [ + 5.8458, + 7.9097 + ], + [ + 7.9605, + 9.8718 + ], + [ + 9.943, + 11.2952 + ], + [ + 11.3968, + 13.8572 + ], + [ + 13.969, + 15.616 + ], + [ + 15.8193, + 17.2528 + ], + [ + 17.446, + 17.8832 + ], + [ + 17.9442, + 21.9193 + ], + [ + 21.9905, + 23.6273 + ], + [ + 23.6883, + 25.01 + ], + [ + 25.0812, + 27.2365 + ], + [ + 27.3178, + 27.6432 + ], + [ + 27.8465, + 31.232 + ], + [ + 31.6997, + 31.8522 + ], + [ + 31.9335, + 35.8578 + ], + [ + 35.929, + 37.4947 + ], + [ + 37.515, + 37.5557 + ], + [ + 37.8302, + 39.5585 + ], + [ + 39.9448, + 41.968 + ], + [ + 41.9883, + 43.7777 + ], + [ + 43.8895, + 45.8822 + ], + [ + 45.9432, + 46.36 + ], + [ + 46.4007, + 47.9053 + ], + [ + 47.9562, + 51.5755 + ], + [ + 51.5857, + 51.789 + ], + [ + 51.8093, + 51.9008 + ], + [ + 51.9517, + 55.9167 + ], + [ + 55.998, + 57.3908 + ], + [ + 57.4213, + 57.8382 + ], + [ + 57.889, + 60.817 + ] + ], + "notes": [ + { + "beat": 0.0, + "dur": 2.0, + "st": -5, + "t": "sitting\u00b7a", + "lead": 0.122, + "w": 0 + }, + { + "beat": 2.0, + "dur": 2.0, + "st": -7, + "t": "sitting\u00b7b", + "lead": 0.0, + "w": 0 + }, + { + "beat": 4.0, + "dur": 1.91, + "st": -9, + "t": "curled", + "lead": 0.0712, + "w": 1 + }, + { + "beat": 5.91, + "dur": 2.09, + "st": -10, + "t": "up", + "lead": 0.122, + "w": 2 + }, + { + "beat": 8.0, + "dur": 2.0, + "st": -12, + "t": "in", + "lead": 0.0813, + "w": 3 + }, + { + "beat": 10.0, + "dur": 1.5, + "st": -7, + "t": "my", + "lead": 0.122, + "w": 4 + }, + { + "beat": 11.5, + "dur": 2.5, + "st": -10, + "t": "self", + "lead": 0.2033, + "w": 4 + }, + { + "beat": 14.0, + "dur": 2.0, + "st": -14, + "t": "i", + "lead": 0.061, + "w": 5 + }, + { + "beat": 16.0, + "dur": 2.0, + "st": -17, + "t": "think", + "lead": 0.3762, + "w": 6 + }, + { + "beat": 18.0, + "dur": 4.0, + "st": 0, + "t": "of", + "lead": 0.1017, + "w": 7 + }, + { + "beat": 22.0, + "dur": 1.75, + "st": -2, + "t": "a", + "lead": 0.0712, + "w": 8 + }, + { + "beat": 23.75, + "dur": 4.25, + "st": -7, + "t": "stone", + "lead": 0.122, + "w": 9 + }, + { + "beat": 28.0, + "dur": 4.0, + "st": -10, + "t": "just", + "lead": 0.305, + "w": 10 + }, + { + "beat": 32.0, + "dur": 2.0, + "st": -9, + "t": "wait", + "lead": 0.1423, + "w": 11 + }, + { + "beat": 34.0, + "dur": 2.0, + "st": -10, + "t": "ing", + "lead": 0.0, + "w": 11 + }, + { + "beat": 36.0, + "dur": 2.0, + "st": -12, + "t": "ve", + "lead": 0.1423, + "w": 12 + }, + { + "beat": 38.0, + "dur": 2.0, + "st": -14, + "t": "ry", + "lead": 0.4372, + "w": 12 + }, + { + "beat": 40.0, + "dur": 2.0, + "st": -5, + "t": "pa", + "lead": 0.1017, + "w": 13 + }, + { + "beat": 42.0, + "dur": 2.0, + "st": -7, + "t": "tient", + "lead": 0.0203, + "w": 13 + }, + { + "beat": 44.0, + "dur": 2.0, + "st": -9, + "t": "ly", + "lead": 0.2237, + "w": 13 + }, + { + "beat": 46.0, + "dur": 2.0, + "st": -7, + "t": "for", + "lead": 0.122, + "w": 14 + }, + { + "beat": 48.0, + "dur": 4.0, + "st": -5, + "t": "time", + "lead": 0.0813, + "w": 15 + }, + { + "beat": 52.0, + "dur": 4.0, + "st": -9, + "t": "to", + "lead": 0.1017, + "w": 16 + }, + { + "beat": 56.0, + "dur": 4.0, + "st": -9, + "t": "pass", + "lead": 0.0712, + "w": 17 + } + ] + }, + "w-sh": { + "leadIn": 0.84, + "beats": 60.0, + "voiced": [ + [ + -0.183, + 1.9622 + ], + [ + 1.9927, + 3.904 + ], + [ + 3.9548, + 4.3818 + ], + [ + 4.392, + 5.7848 + ], + [ + 5.8662, + 6.2118 + ], + [ + 7.93, + 8.6417 + ], + [ + 8.7027, + 9.9227 + ], + [ + 9.9735, + 10.8275 + ], + [ + 10.8783, + 11.4477 + ], + [ + 11.4782, + 12.6168 + ], + [ + 13.176, + 13.7148 + ], + [ + 13.9893, + 15.4737 + ], + [ + 15.8295, + 16.6022 + ], + [ + 16.9783, + 17.751 + ], + [ + 17.9442, + 19.4997 + ], + [ + 19.581, + 21.8685 + ], + [ + 21.9397, + 23.6477 + ], + [ + 23.7087, + 25.7725 + ], + [ + 25.7928, + 26.0572 + ], + [ + 26.0673, + 27.8872 + ], + [ + 27.9482, + 28.1515 + ], + [ + 28.2837, + 29.3003 + ], + [ + 29.3512, + 30.9677 + ], + [ + 30.9982, + 31.8013 + ], + [ + 33.5297, + 35.929 + ], + [ + 35.99, + 36.478 + ], + [ + 36.4983, + 37.027 + ], + [ + 37.0473, + 37.9013 + ], + [ + 37.9522, + 39.894 + ], + [ + 40.7378, + 42.9338 + ], + [ + 42.944, + 43.6455 + ], + [ + 43.8285, + 45.567 + ], + [ + 45.8212, + 47.5698 + ], + [ + 47.6003, + 47.8952 + ], + [ + 47.946, + 51.1688 + ], + [ + 51.2197, + 51.7687 + ], + [ + 51.972, + 55.3575 + ], + [ + 55.4083, + 55.7438 + ], + [ + 55.876, + 56.2217 + ], + [ + 56.2318, + 56.5775 + ], + [ + 56.608, + 58.743 + ], + [ + 58.987, + 59.4852 + ], + [ + 59.5157, + 59.8105 + ], + [ + 59.8308, + 59.963 + ], + [ + 60.0037, + 60.0748 + ], + [ + 60.4103, + 60.5425 + ] + ], + "notes": [ + { + "beat": 0.0, + "dur": 2.0, + "st": -5, + "t": "sitting\u00b7a", + "lead": 0.9557, + "w": 0 + }, + { + "beat": 2.0, + "dur": 2.0, + "st": -7, + "t": "sitting\u00b7b", + "lead": 0.0203, + "w": 0 + }, + { + "beat": 4.0, + "dur": 1.91, + "st": -9, + "t": "curled", + "lead": 0.0813, + "w": 1 + }, + { + "beat": 5.91, + "dur": 2.09, + "st": -10, + "t": "up", + "lead": 0.0813, + "w": 2 + }, + { + "beat": 8.0, + "dur": 2.0, + "st": -12, + "t": "in", + "lead": 0.1423, + "w": 3 + }, + { + "beat": 10.0, + "dur": 1.5, + "st": -7, + "t": "my", + "lead": 0.061, + "w": 4 + }, + { + "beat": 11.5, + "dur": 2.5, + "st": -10, + "t": "self", + "lead": 0.0407, + "w": 4 + }, + { + "beat": 14.0, + "dur": 2.0, + "st": -14, + "t": "i", + "lead": 0.1423, + "w": 5 + }, + { + "beat": 16.0, + "dur": 2.0, + "st": -17, + "t": "think", + "lead": 0.5185, + "w": 6 + }, + { + "beat": 18.0, + "dur": 4.0, + "st": 0, + "t": "of", + "lead": 0.1017, + "w": 7 + }, + { + "beat": 22.0, + "dur": 1.75, + "st": -2, + "t": "a", + "lead": 0.122, + "w": 8 + }, + { + "beat": 23.75, + "dur": 4.25, + "st": -7, + "t": "stone", + "lead": 0.0915, + "w": 9 + }, + { + "beat": 28.0, + "dur": 4.0, + "st": -10, + "t": "just", + "lead": 0.1017, + "w": 10 + }, + { + "beat": 32.0, + "dur": 2.0, + "st": -9, + "t": "wait", + "lead": 0.0, + "w": 11 + }, + { + "beat": 34.0, + "dur": 2.0, + "st": -10, + "t": "ing", + "lead": 0.0, + "w": 11 + }, + { + "beat": 36.0, + "dur": 2.0, + "st": -12, + "t": "ve", + "lead": 0.0712, + "w": 12 + }, + { + "beat": 38.0, + "dur": 2.0, + "st": -14, + "t": "ry", + "lead": 0.1017, + "w": 12 + }, + { + "beat": 40.0, + "dur": 2.0, + "st": -5, + "t": "pa", + "lead": 0.0, + "w": 13 + }, + { + "beat": 42.0, + "dur": 2.0, + "st": -7, + "t": "tient", + "lead": 0.0, + "w": 13 + }, + { + "beat": 44.0, + "dur": 2.0, + "st": -9, + "t": "ly", + "lead": 0.3457, + "w": 13 + }, + { + "beat": 46.0, + "dur": 2.0, + "st": -7, + "t": "for", + "lead": 0.4372, + "w": 14 + }, + { + "beat": 48.0, + "dur": 4.0, + "st": -5, + "t": "time", + "lead": 0.1017, + "w": 15 + }, + { + "beat": 52.0, + "dur": 4.0, + "st": -9, + "t": "to", + "lead": 0.061, + "w": 16 + }, + { + "beat": 56.0, + "dur": 4.0, + "st": -9, + "t": "pass", + "lead": 0.244, + "w": 17 + } + ] + }, + "w-lg": { + "leadIn": 0.575, + "beats": 60.0, + "voiced": [ + [ + -0.183, + 3.8633 + ], + [ + 3.9345, + 4.2802 + ], + [ + 4.2903, + 5.9068 + ], + [ + 7.1065, + 7.8588 + ], + [ + 7.9402, + 9.8922 + ], + [ + 9.9532, + 10.8783 + ], + [ + 10.9088, + 11.4985 + ], + [ + 13.9487, + 15.8803 + ], + [ + 15.9515, + 16.714 + ], + [ + 16.7852, + 17.7815 + ], + [ + 18.3508, + 21.899 + ], + [ + 21.9702, + 23.6578 + ], + [ + 23.729, + 25.6607 + ], + [ + 25.7725, + 27.4703 + ], + [ + 27.8465, + 28.7818 + ], + [ + 28.8123, + 30.7135 + ], + [ + 31.9437, + 35.8985 + ], + [ + 35.9493, + 37.9623 + ], + [ + 40.077, + 41.724 + ], + [ + 41.8663, + 43.6963 + ], + [ + 43.9302, + 45.4857 + ], + [ + 45.8212, + 47.5393 + ], + [ + 47.6207, + 47.8647 + ], + [ + 47.9358, + 51.0977 + ], + [ + 51.8195, + 55.9167 + ], + [ + 56.6283, + 59.5157 + ] + ], + "notes": [ + { + "beat": 0.0, + "dur": 2.0, + "st": 7, + "t": "sitting\u00b7a", + "lead": 0.4168, + "w": 0 + }, + { + "beat": 2.0, + "dur": 2.0, + "st": 5, + "t": "sitting\u00b7b", + "lead": 0.0, + "w": 0 + }, + { + "beat": 4.0, + "dur": 1.91, + "st": 3, + "t": "curled", + "lead": 0.122, + "w": 1 + }, + { + "beat": 5.91, + "dur": 2.09, + "st": 2, + "t": "up", + "lead": 0.0, + "w": 2 + }, + { + "beat": 8.0, + "dur": 2.0, + "st": 0, + "t": "in", + "lead": 0.122, + "w": 3 + }, + { + "beat": 10.0, + "dur": 1.5, + "st": 5, + "t": "my", + "lead": 0.1017, + "w": 4 + }, + { + "beat": 11.5, + "dur": 2.5, + "st": 2, + "t": "self", + "lead": 0.0, + "w": 4 + }, + { + "beat": 14.0, + "dur": 2.0, + "st": -2, + "t": "i", + "lead": 0.1017, + "w": 5 + }, + { + "beat": 16.0, + "dur": 2.0, + "st": -5, + "t": "think", + "lead": 0.1017, + "w": 6 + }, + { + "beat": 18.0, + "dur": 4.0, + "st": 12, + "t": "of", + "lead": 0.0, + "w": 7 + }, + { + "beat": 22.0, + "dur": 1.75, + "st": 10, + "t": "a", + "lead": 0.0915, + "w": 8 + }, + { + "beat": 23.75, + "dur": 4.25, + "st": 5, + "t": "stone", + "lead": 0.0813, + "w": 9 + }, + { + "beat": 28.0, + "dur": 4.0, + "st": 2, + "t": "just", + "lead": 0.305, + "w": 10 + }, + { + "beat": 32.0, + "dur": 2.0, + "st": 3, + "t": "wait", + "lead": 0.122, + "w": 11 + }, + { + "beat": 34.0, + "dur": 2.0, + "st": 2, + "t": "ing", + "lead": 0.0, + "w": 11 + }, + { + "beat": 36.0, + "dur": 2.0, + "st": 0, + "t": "ve", + "lead": 0.1017, + "w": 12 + }, + { + "beat": 38.0, + "dur": 2.0, + "st": -2, + "t": "ry", + "lead": 0.0, + "w": 12 + }, + { + "beat": 40.0, + "dur": 2.0, + "st": 7, + "t": "pa", + "lead": 0.0, + "w": 13 + }, + { + "beat": 42.0, + "dur": 2.0, + "st": 5, + "t": "tient", + "lead": 0.2643, + "w": 13 + }, + { + "beat": 44.0, + "dur": 2.0, + "st": 3, + "t": "ly", + "lead": 0.1423, + "w": 13 + }, + { + "beat": 46.0, + "dur": 2.0, + "st": 5, + "t": "for", + "lead": 0.5083, + "w": 14 + }, + { + "beat": 48.0, + "dur": 4.0, + "st": 7, + "t": "time", + "lead": 0.122, + "w": 15 + }, + { + "beat": 52.0, + "dur": 4.0, + "st": 3, + "t": "to", + "lead": 0.5795, + "w": 16 + }, + { + "beat": 56.0, + "dur": 4.0, + "st": 3, + "t": "pass", + "lead": 0.0, + "w": 17 + } + ] + }, + "w-pf": { + "leadIn": 0.765, + "beats": 60.0, + "voiced": [ + [ + -0.183, + 1.9012 + ], + [ + 2.44, + 3.7007 + ], + [ + 4.148, + 5.0935 + ], + [ + 5.1647, + 5.7543 + ], + [ + 6.6083, + 7.8588 + ], + [ + 7.9402, + 8.4587 + ], + [ + 8.54, + 9.9837 + ], + [ + 11.3968, + 13.4302 + ], + [ + 13.7657, + 13.9893 + ], + [ + 15.9515, + 16.4497 + ], + [ + 16.5717, + 17.3545 + ], + [ + 17.9442, + 19.4285 + ], + [ + 19.7335, + 21.8888 + ], + [ + 21.9498, + 23.6375 + ], + [ + 23.6985, + 26.1995 + ], + [ + 26.413, + 27.8363 + ], + [ + 28.3853, + 31.0693 + ], + [ + 33.8143, + 34.4142 + ], + [ + 34.4243, + 34.7802 + ], + [ + 34.7903, + 35.38 + ], + [ + 35.4003, + 35.6748 + ], + [ + 35.9087, + 37.1185 + ], + [ + 37.1287, + 37.8098 + ], + [ + 39.9448, + 40.3108 + ], + [ + 40.4328, + 41.541 + ], + [ + 44.3165, + 45.4043 + ], + [ + 45.8212, + 46.482 + ], + [ + 47.153, + 47.824 + ], + [ + 47.9155, + 49.9183 + ], + [ + 52.3177, + 53.4055 + ], + [ + 53.6292, + 55.6523 + ], + [ + 56.4657, + 57.5433 + ], + [ + 57.5738, + 59.0988 + ] + ], + "notes": [ + { + "beat": 0.0, + "dur": 2.0, + "st": 7, + "t": "sitting\u00b7a", + "lead": 0.8032, + "w": 0 + }, + { + "beat": 2.0, + "dur": 2.0, + "st": 5, + "t": "sitting\u00b7b", + "lead": 0.0, + "w": 0 }, { "beat": 4.0, + "dur": 1.91, + "st": 3, + "t": "curled", + "lead": 0.0, + "w": 1 + }, + { + "beat": 5.91, + "dur": 2.09, + "st": 2, + "t": "up", + "lead": 0.0, + "w": 2 + }, + { + "beat": 8.0, + "dur": 2.0, + "st": 0, + "t": "in", + "lead": 0.122, + "w": 3 + }, + { + "beat": 10.0, "dur": 1.5, + "st": 5, + "t": "my", + "lead": 0.0, + "w": 4 + }, + { + "beat": 11.5, + "dur": 2.5, + "st": 2, + "t": "self", + "lead": 0.2033, + "w": 4 + }, + { + "beat": 14.0, + "dur": 2.0, + "st": -2, + "t": "i", + "lead": 0.0, + "w": 5 + }, + { + "beat": 16.0, + "dur": 2.0, + "st": -5, + "t": "think", + "lead": 0.1017, + "w": 6 + }, + { + "beat": 18.0, + "dur": 4.0, + "st": 12, + "t": "of", + "lead": 0.1017, + "w": 7 + }, + { + "beat": 22.0, + "dur": 1.75, + "st": 10, + "t": "a", + "lead": 0.1017, + "w": 8 + }, + { + "beat": 23.75, + "dur": 4.25, + "st": 5, + "t": "stone", + "lead": 0.1017, + "w": 9 + }, + { + "beat": 28.0, + "dur": 4.0, + "st": 2, + "t": "just", + "lead": 0.0, + "w": 10 + }, + { + "beat": 32.0, + "dur": 2.0, + "st": 3, + "t": "wait", + "lead": 0.0, + "w": 11 + }, + { + "beat": 34.0, + "dur": 2.0, + "st": 2, + "t": "ing", + "lead": 0.3965, + "w": 11 + }, + { + "beat": 36.0, + "dur": 2.0, + "st": 0, + "t": "ve", + "lead": 0.3253, + "w": 12 + }, + { + "beat": 38.0, + "dur": 2.0, + "st": -2, + "t": "ry", + "lead": 0.183, + "w": 12 + }, + { + "beat": 40.0, + "dur": 2.0, + "st": 7, + "t": "pa", + "lead": 0.1017, + "w": 13 + }, + { + "beat": 42.0, + "dur": 2.0, + "st": 5, + "t": "tient", + "lead": 0.0, + "w": 13 + }, + { + "beat": 44.0, + "dur": 2.0, + "st": 3, + "t": "ly", + "lead": 0.0, + "w": 13 + }, + { + "beat": 46.0, + "dur": 2.0, + "st": 5, + "t": "for", + "lead": 0.366, + "w": 14 + }, + { + "beat": 48.0, + "dur": 4.0, + "st": 7, + "t": "time", + "lead": 0.1627, + "w": 15 + }, + { + "beat": 52.0, + "dur": 4.0, + "st": 3, + "t": "to", + "lead": 0.0, + "w": 16 + }, + { + "beat": 56.0, + "dur": 4.0, "st": 3, "t": "pass", - "lead": 0.0 + "lead": 0.0, + "w": 17 + } + ] + }, + "w-rd": { + "leadIn": 0.405, + "beats": 60.0, + "voiced": [ + [ + -0.0203, + 1.3827 + ], + [ + 1.9215, + 3.8328 + ], + [ + 3.9345, + 4.9105 + ], + [ + 4.9308, + 5.7238 + ], + [ + 6.3135, + 7.8893 + ], + [ + 7.9503, + 9.8312 + ], + [ + 10.3802, + 11.4883 + ], + [ + 12.0475, + 13.969 + ], + [ + 16.714, + 17.8018 + ], + [ + 17.9747, + 21.8685 + ], + [ + 21.9397, + 23.6375 + ], + [ + 23.6985, + 25.681 + ], + [ + 25.864, + 27.1552 + ], + [ + 27.8262, + 30.5407 + ], + [ + 31.8827, + 32.0047 + ], + [ + 33.8753, + 34.1295 + ], + [ + 34.5565, + 34.9937 + ], + [ + 35.014, + 35.6443 + ], + [ + 35.685, + 35.8985 + ], + [ + 35.9493, + 37.9115 + ], + [ + 37.9928, + 39.9042 + ], + [ + 40.26, + 40.443 + ], + [ + 40.4532, + 41.9883 + ], + [ + 46.848, + 47.885 + ], + [ + 47.946, + 47.9968 + ], + [ + 48.1493, + 48.7492 + ], + [ + 48.8, + 50.5283 + ], + [ + 50.5588, + 51.5653 + ], + [ + 57.34, + 60.817 + ] + ], + "notes": [ + { + "beat": 0.0, + "dur": 2.0, + "st": 7, + "t": "sitting\u00b7a", + "lead": 0.0712, + "w": 0 + }, + { + "beat": 2.0, + "dur": 2.0, + "st": 5, + "t": "sitting\u00b7b", + "lead": 0.1627, + "w": 0 + }, + { + "beat": 4.0, + "dur": 1.91, + "st": 3, + "t": "curled", + "lead": 0.122, + "w": 1 + }, + { + "beat": 5.91, + "dur": 2.09, + "st": 2, + "t": "up", + "lead": 0.0, + "w": 2 + }, + { + "beat": 8.0, + "dur": 2.0, + "st": 0, + "t": "in", + "lead": 0.1017, + "w": 3 + }, + { + "beat": 10.0, + "dur": 1.5, + "st": 5, + "t": "my", + "lead": 0.0, + "w": 4 + }, + { + "beat": 11.5, + "dur": 2.5, + "st": 2, + "t": "self", + "lead": 0.0, + "w": 4 + }, + { + "beat": 14.0, + "dur": 2.0, + "st": -2, + "t": "i", + "lead": 0.0, + "w": 5 + }, + { + "beat": 16.0, + "dur": 2.0, + "st": -5, + "t": "think", + "lead": 0.0, + "w": 6 + }, + { + "beat": 18.0, + "dur": 4.0, + "st": 12, + "t": "of", + "lead": 0.0712, + "w": 7 + }, + { + "beat": 22.0, + "dur": 1.75, + "st": 10, + "t": "a", + "lead": 0.122, + "w": 8 + }, + { + "beat": 23.75, + "dur": 4.25, + "st": 5, + "t": "stone", + "lead": 0.1017, + "w": 9 + }, + { + "beat": 28.0, + "dur": 4.0, + "st": 2, + "t": "just", + "lead": 0.3457, + "w": 10 + }, + { + "beat": 32.0, + "dur": 2.0, + "st": 3, + "t": "wait", + "lead": 0.244, + "w": 11 + }, + { + "beat": 34.0, + "dur": 2.0, + "st": 2, + "t": "ing", + "lead": 0.5287, + "w": 11 + }, + { + "beat": 36.0, + "dur": 2.0, + "st": 0, + "t": "ve", + "lead": 0.1017, + "w": 12 + }, + { + "beat": 38.0, + "dur": 2.0, + "st": -2, + "t": "ry", + "lead": 0.0203, + "w": 12 + }, + { + "beat": 40.0, + "dur": 2.0, + "st": 7, + "t": "pa", + "lead": 0.0, + "w": 13 + }, + { + "beat": 42.0, + "dur": 2.0, + "st": 5, + "t": "tient", + "lead": 0.0, + "w": 13 + }, + { + "beat": 44.0, + "dur": 2.0, + "st": 3, + "t": "ly", + "lead": 0.0, + "w": 13 + }, + { + "beat": 46.0, + "dur": 2.0, + "st": 5, + "t": "for", + "lead": 0.0, + "w": 14 + }, + { + "beat": 48.0, + "dur": 4.0, + "st": 7, + "t": "time", + "lead": 0.1017, + "w": 15 + }, + { + "beat": 52.0, + "dur": 4.0, + "st": 3, + "t": "to", + "lead": 0.0, + "w": 16 + }, + { + "beat": 56.0, + "dur": 4.0, + "st": 3, + "t": "pass", + "lead": 0.0, + "w": 17 + } + ] + }, + "w-cp": { + "leadIn": 0.43, + "beats": 60.0, + "voiced": [ + [ + -0.061, + 3.6498 + ], + [ + 3.8837, + 5.4392 + ], + [ + 5.7238, + 5.7645 + ], + [ + 6.4457, + 7.8792 + ], + [ + 7.9605, + 9.9023 + ], + [ + 9.9633, + 11.4985 + ], + [ + 16.6225, + 17.7612 + ], + [ + 17.934, + 21.8685 + ], + [ + 21.9397, + 23.7392 + ], + [ + 24.2882, + 27.8973 + ], + [ + 27.9685, + 30.1848 + ], + [ + 30.5203, + 30.6525 + ], + [ + 30.7135, + 31.8928 + ], + [ + 31.9538, + 33.0925 + ], + [ + 33.8143, + 35.4105 + ], + [ + 35.8375, + 35.99 + ], + [ + 42.7712, + 43.2287 + ], + [ + 43.8183, + 45.8923 + ], + [ + 45.9533, + 47.5597 + ], + [ + 55.8252, + 56.3843 + ] + ], + "notes": [ + { + "beat": 0.0, + "dur": 2.0, + "st": -5, + "t": "sitting\u00b7a", + "lead": 0.122, + "w": 0 + }, + { + "beat": 2.0, + "dur": 2.0, + "st": -7, + "t": "sitting\u00b7b", + "lead": 0.0, + "w": 0 + }, + { + "beat": 4.0, + "dur": 1.91, + "st": -9, + "t": "curled", + "lead": 0.3253, + "w": 1 + }, + { + "beat": 5.91, + "dur": 2.09, + "st": -10, + "t": "up", + "lead": 0.4677, + "w": 2 + }, + { + "beat": 8.0, + "dur": 2.0, + "st": -12, + "t": "in", + "lead": 0.0915, + "w": 3 + }, + { + "beat": 10.0, + "dur": 1.5, + "st": -7, + "t": "my", + "lead": 0.0915, + "w": 4 + }, + { + "beat": 11.5, + "dur": 2.5, + "st": -10, + "t": "self", + "lead": 0.0, + "w": 4 + }, + { + "beat": 14.0, + "dur": 2.0, + "st": -14, + "t": "i", + "lead": 0.0, + "w": 5 + }, + { + "beat": 16.0, + "dur": 2.0, + "st": -17, + "t": "think", + "lead": 0.0, + "w": 6 + }, + { + "beat": 18.0, + "dur": 4.0, + "st": 0, + "t": "of", + "lead": 0.122, + "w": 7 + }, + { + "beat": 22.0, + "dur": 1.75, + "st": -2, + "t": "a", + "lead": 0.122, + "w": 8 + }, + { + "beat": 23.75, + "dur": 4.25, + "st": -7, + "t": "stone", + "lead": 0.0, + "w": 9 + }, + { + "beat": 28.0, + "dur": 4.0, + "st": -10, + "t": "just", + "lead": 0.0915, + "w": 10 + }, + { + "beat": 32.0, + "dur": 2.0, + "st": -9, + "t": "wait", + "lead": 0.1017, + "w": 11 + }, + { + "beat": 34.0, + "dur": 2.0, + "st": -10, + "t": "ing", + "lead": 0.5388, + "w": 11 + }, + { + "beat": 36.0, + "dur": 2.0, + "st": -12, + "t": "ve", + "lead": 0.5083, + "w": 12 + }, + { + "beat": 38.0, + "dur": 2.0, + "st": -14, + "t": "ry", + "lead": 0.0, + "w": 12 + }, + { + "beat": 40.0, + "dur": 2.0, + "st": -5, + "t": "pa", + "lead": 0.0, + "w": 13 + }, + { + "beat": 42.0, + "dur": 2.0, + "st": -7, + "t": "tient", + "lead": 0.0, + "w": 13 + }, + { + "beat": 44.0, + "dur": 2.0, + "st": -9, + "t": "ly", + "lead": 0.366, + "w": 13 + }, + { + "beat": 46.0, + "dur": 2.0, + "st": -7, + "t": "for", + "lead": 0.1017, + "w": 14 + }, + { + "beat": 48.0, + "dur": 4.0, + "st": -5, + "t": "time", + "lead": 0.0, + "w": 15 + }, + { + "beat": 52.0, + "dur": 4.0, + "st": -9, + "t": "to", + "lead": 0.0, + "w": 16 + }, + { + "beat": 56.0, + "dur": 4.0, + "st": -9, + "t": "pass", + "lead": 0.3457, + "w": 17 + } + ] + }, + "w-s": { + "leadIn": 0.37, + "beats": 60.0, + "voiced": [ + [ + 1.8198, + 3.8938 + ], + [ + 3.9447, + 7.1675 + ], + [ + 7.3403, + 7.8792 + ], + [ + 7.9503, + 9.8718 + ], + [ + 9.943, + 11.4477 + ], + [ + 11.4782, + 13.6945 + ], + [ + 13.7148, + 13.908 + ], + [ + 13.969, + 15.8803 + ], + [ + 15.9515, + 16.6327 + ], + [ + 16.7038, + 16.8055 + ], + [ + 16.8258, + 17.0698 + ], + [ + 17.1003, + 17.5578 + ], + [ + 17.629, + 17.8832 + ], + [ + 17.9442, + 21.8888 + ], + [ + 21.96, + 23.6172 + ], + [ + 23.6883, + 25.986 + ], + [ + 26.108, + 27.9583 + ], + [ + 28.1108, + 31.9945 + ], + [ + 33.9465, + 35.8782 + ], + [ + 35.9392, + 39.8838 + ], + [ + 39.9448, + 41.7037 + ], + [ + 41.8663, + 43.8895 + ], + [ + 43.9607, + 44.6418 + ], + [ + 44.6825, + 45.7703 + ], + [ + 45.811, + 45.8822 + ], + [ + 45.9432, + 47.1632 + ], + [ + 47.1937, + 47.885 + ], + [ + 47.9663, + 50.5385 + ], + [ + 51.1383, + 51.8703 + ], + [ + 51.9415, + 54.534 + ], + [ + 54.778, + 55.8862 + ], + [ + 55.9472, + 59.6173 + ] + ], + "notes": [ + { + "beat": 0.0, + "dur": 2.0, + "st": 7, + "t": "sitting\u00b7a", + "lead": 0.0, + "w": 0 + }, + { + "beat": 2.0, + "dur": 2.0, + "st": 5, + "t": "sitting\u00b7b", + "lead": 0.4473, + "w": 0 + }, + { + "beat": 4.0, + "dur": 1.91, + "st": 3, + "t": "curled", + "lead": 0.1017, + "w": 1 + }, + { + "beat": 5.91, + "dur": 2.09, + "st": 2, + "t": "up", + "lead": 0.0, + "w": 2 + }, + { + "beat": 8.0, + "dur": 2.0, + "st": 0, + "t": "in", + "lead": 0.1017, + "w": 3 + }, + { + "beat": 10.0, + "dur": 1.5, + "st": 5, + "t": "my", + "lead": 0.122, + "w": 4 + }, + { + "beat": 11.5, + "dur": 2.5, + "st": 2, + "t": "self", + "lead": 0.0407, + "w": 4 + }, + { + "beat": 14.0, + "dur": 2.0, + "st": -2, + "t": "i", + "lead": 0.0813, + "w": 5 + }, + { + "beat": 16.0, + "dur": 2.0, + "st": -5, + "t": "think", + "lead": 0.1017, + "w": 6 + }, + { + "beat": 18.0, + "dur": 4.0, + "st": 12, + "t": "of", + "lead": 0.1017, + "w": 7 + }, + { + "beat": 22.0, + "dur": 1.75, + "st": 10, + "t": "a", + "lead": 0.1017, + "w": 8 + }, + { + "beat": 23.75, + "dur": 4.25, + "st": 5, + "t": "stone", + "lead": 0.122, + "w": 9 + }, + { + "beat": 28.0, + "dur": 4.0, + "st": 2, + "t": "just", + "lead": 0.0, + "w": 10 + }, + { + "beat": 32.0, + "dur": 2.0, + "st": 3, + "t": "wait", + "lead": 0.0, + "w": 11 + }, + { + "beat": 34.0, + "dur": 2.0, + "st": 2, + "t": "ing", + "lead": 0.0, + "w": 11 + }, + { + "beat": 36.0, + "dur": 2.0, + "st": 0, + "t": "ve", + "lead": 0.122, + "w": 12 + }, + { + "beat": 38.0, + "dur": 2.0, + "st": -2, + "t": "ry", + "lead": 0.0, + "w": 12 + }, + { + "beat": 40.0, + "dur": 2.0, + "st": 7, + "t": "pa", + "lead": 0.1017, + "w": 13 + }, + { + "beat": 42.0, + "dur": 2.0, + "st": 5, + "t": "tient", + "lead": 0.2643, + "w": 13 + }, + { + "beat": 44.0, + "dur": 2.0, + "st": 3, + "t": "ly", + "lead": 0.0813, + "w": 13 + }, + { + "beat": 46.0, + "dur": 2.0, + "st": 5, + "t": "for", + "lead": 0.122, + "w": 14 + }, + { + "beat": 48.0, + "dur": 4.0, + "st": 7, + "t": "time", + "lead": 0.1017, + "w": 15 + }, + { + "beat": 52.0, + "dur": 4.0, + "st": 3, + "t": "to", + "lead": 0.122, + "w": 16 + }, + { + "beat": 56.0, + "dur": 4.0, + "st": 3, + "t": "pass", + "lead": 0.1017, + "w": 17 + } + ] + }, + "w-o": { + "leadIn": 0.55, + "beats": 60.0, + "voiced": [ + [ + -0.183, + 3.8633 + ], + [ + 3.9345, + 5.8052 + ], + [ + 5.856, + 7.7572 + ], + [ + 7.9503, + 9.8922 + ], + [ + 9.9532, + 11.1122 + ], + [ + 11.3562, + 13.7555 + ], + [ + 13.9283, + 15.6262 + ], + [ + 16.0023, + 16.2158 + ], + [ + 16.2565, + 16.47 + ], + [ + 16.5615, + 16.7852 + ], + [ + 16.8258, + 17.385 + ], + [ + 17.934, + 21.8685 + ], + [ + 21.9397, + 23.7392 + ], + [ + 23.7493, + 26.2402 + ], + [ + 26.3012, + 27.9177 + ], + [ + 27.9787, + 28.7513 + ], + [ + 28.9343, + 31.2523 + ], + [ + 31.476, + 31.8522 + ], + [ + 31.9335, + 35.8883 + ], + [ + 35.9493, + 37.576 + ], + [ + 37.8607, + 39.8533 + ], + [ + 39.9347, + 40.504 + ], + [ + 40.5243, + 41.8765 + ], + [ + 41.9375, + 45.872 + ], + [ + 45.9432, + 47.458 + ], + [ + 47.5597, + 47.885 + ], + [ + 47.946, + 50.8638 + ], + [ + 50.9858, + 51.8907 + ], + [ + 51.9517, + 55.9675 + ], + [ + 57.6043, + 59.1395 + ] + ], + "notes": [ + { + "beat": 0.0, + "dur": 2.0, + "st": 7, + "t": "sitting\u00b7a", + "lead": 0.366, + "w": 0 + }, + { + "beat": 2.0, + "dur": 2.0, + "st": 5, + "t": "sitting\u00b7b", + "lead": 0.0, + "w": 0 + }, + { + "beat": 4.0, + "dur": 1.91, + "st": 3, + "t": "curled", + "lead": 0.122, + "w": 1 + }, + { + "beat": 5.91, + "dur": 2.09, + "st": 2, + "t": "up", + "lead": 0.1017, + "w": 2 + }, + { + "beat": 8.0, + "dur": 2.0, + "st": 0, + "t": "in", + "lead": 0.1017, + "w": 3 + }, + { + "beat": 10.0, + "dur": 1.5, + "st": 5, + "t": "my", + "lead": 0.1017, + "w": 4 + }, + { + "beat": 11.5, + "dur": 2.5, + "st": 2, + "t": "self", + "lead": 0.3863, + "w": 4 + }, + { + "beat": 14.0, + "dur": 2.0, + "st": -2, + "t": "i", + "lead": 0.1423, + "w": 5 + }, + { + "beat": 16.0, + "dur": 2.0, + "st": -5, + "t": "think", + "lead": 0.3558, + "w": 6 + }, + { + "beat": 18.0, + "dur": 4.0, + "st": 12, + "t": "of", + "lead": 0.122, + "w": 7 + }, + { + "beat": 22.0, + "dur": 1.75, + "st": 10, + "t": "a", + "lead": 0.122, + "w": 8 + }, + { + "beat": 23.75, + "dur": 4.25, + "st": 5, + "t": "stone", + "lead": 0.0, + "w": 9 + }, + { + "beat": 28.0, + "dur": 4.0, + "st": 2, + "t": "just", + "lead": 0.0813, + "w": 10 + }, + { + "beat": 32.0, + "dur": 2.0, + "st": 3, + "t": "wait", + "lead": 0.1423, + "w": 11 + }, + { + "beat": 34.0, + "dur": 2.0, + "st": 2, + "t": "ing", + "lead": 0.0, + "w": 11 + }, + { + "beat": 36.0, + "dur": 2.0, + "st": 0, + "t": "ve", + "lead": 0.1017, + "w": 12 + }, + { + "beat": 38.0, + "dur": 2.0, + "st": -2, + "t": "ry", + "lead": 0.4168, + "w": 12 + }, + { + "beat": 40.0, + "dur": 2.0, + "st": 7, + "t": "pa", + "lead": 0.122, + "w": 13 + }, + { + "beat": 42.0, + "dur": 2.0, + "st": 5, + "t": "tient", + "lead": 0.122, + "w": 13 + }, + { + "beat": 44.0, + "dur": 2.0, + "st": 3, + "t": "ly", + "lead": 0.0, + "w": 13 + }, + { + "beat": 46.0, + "dur": 2.0, + "st": 5, + "t": "for", + "lead": 0.122, + "w": 14 + }, + { + "beat": 48.0, + "dur": 4.0, + "st": 7, + "t": "time", + "lead": 0.1017, + "w": 15 + }, + { + "beat": 52.0, + "dur": 4.0, + "st": 3, + "t": "to", + "lead": 0.1017, + "w": 16 + }, + { + "beat": 56.0, + "dur": 4.0, + "st": 3, + "t": "pass", + "lead": 0.0, + "w": 17 } ] } diff --git a/pop/loner/vox4/.manifest.json b/pop/loner/vox4/.manifest.json --- a/pop/loner/vox4/.manifest.json +++ b/pop/loner/vox4/.manifest.json @@ -1,161 +1,331 @@ { "w-whole-line": { "slice": "f-whole-line", - "lead_in": 0.04, + "lead_in": 0.33, "spans": [ [ "sitting\u00b7a", 0.0, - 0.755 + 1.0 ], [ "sitting\u00b7b", - 0.755, - 1.51 + 1.0, + 1.73 ], [ "curled", - 1.51, - 2.4 + 1.73, + 2.62 ], [ "up", - 2.4, - 2.995 + 2.62, + 3.215 ], [ "in", - 3.22, - 3.89 + 3.44, + 4.11 ], [ "my", - 3.89, - 4.5 + 4.11, + 4.72 ], [ "self", - 4.5, - 5.5 + 4.72, + 5.72 ], [ "i", - 5.5, - 6.215 + 5.72, + 6.44 ], [ "think", - 6.215, - 7.15 + 6.44, + 7.37 ], [ "of", - 7.15, - 8.76 + 7.37, + 8.98 ], [ "a", - 8.76, - 9.555 + 8.98, + 9.41 ], [ "stone", - 9.555, - 10.52 + 9.41, + 10.74 ], [ "just", - 11.195, - 12.425 + 11.285, + 12.645 ], [ "wait", - 12.67, - 13.7 + 12.89, + 13.92 ], [ "ing", - 13.7, - 14.4 + 13.92, + 14.62 ], [ "ve", - 14.4, - 15.05 + 14.62, + 15.39 ], [ "ry", - 15.05, - 16.04 + 15.39, + 16.12 ], [ "pa", - 16.04, - 16.8 + 16.12, + 16.875 ], [ "tient", - 16.8, - 17.7 + 16.875, + 17.92 ], [ "ly", - 17.7, - 18.54 + 17.92, + 18.76 ], [ "for", - 18.54, - 19.48 + 18.76, + 19.535 ], [ "time", - 19.48, - 20.405 + 19.535, + 20.625 ], [ "to", - 21.2, - 23.0 + 21.42, + 22.38 ], [ "pass", 23.0, - 23.97 + 24.55 ] ], - "beats": 59.0, + "pins": [ + { + "t": "sitting\u00b7a", + "pin": 0, + "cut": null + }, + { + "t": "sitting\u00b7b", + "pin": 0, + "cut": 1 + }, + { + "t": "curled", + "pin": 1, + "cut": null + }, + { + "t": "up", + "pin": 2, + "cut": null + }, + { + "t": "in", + "pin": 3, + "cut": null + }, + { + "t": "my", + "pin": 4, + "cut": null + }, + { + "t": "self", + "pin": 4, + "cut": 1 + }, + { + "t": "i", + "pin": 5, + "cut": null + }, + { + "t": "think", + "pin": 6, + "cut": null + }, + { + "t": "of", + "pin": 7, + "cut": null + }, + { + "t": "a", + "pin": 8, + "cut": null + }, + { + "t": "stone", + "pin": 9, + "cut": null + }, + { + "t": "just", + "pin": 10, + "cut": null + }, + { + "t": "wait", + "pin": 11, + "cut": null + }, + { + "t": "ing", + "pin": 11, + "cut": 1 + }, + { + "t": "ve", + "pin": 12, + "cut": null + }, + { + "t": "ry", + "pin": 12, + "cut": 1 + }, + { + "t": "pa", + "pin": 13, + "cut": null + }, + { + "t": "tient", + "pin": 13, + "cut": 1 + }, + { + "t": "ly", + "pin": 13, + "cut": 2 + }, + { + "t": "for", + "pin": 14, + "cut": null + }, + { + "t": "time", + "pin": 15, + "cut": null + }, + { + "t": "to", + "pin": 16, + "cut": null + }, + { + "t": "pass", + "pin": 17, + "cut": null + } + ], + "beats": 60.0, "renders": { - "lead": 29.455 + "lead": 30.24 }, "snaps": [ "in +80ms", "my -50ms", "i +180ms", - "think -45ms", - "a -40ms", - "stone -45ms", - "just +80ms", - "pa +80ms" + "think -40ms", + "a -40ms" ], "trims": [ "up \u2212225ms", - "stone \u2212675ms", + "stone \u2212575ms", "just \u2212275ms", - "time \u2212795ms" + "time \u2212795ms", + "to \u2212650ms" ], "words": "the whole lyric, one take" }, "w-sitting-curled": { "slice": "f-sitting-curled", - "lead_in": 0.02, + "lead_in": 0.04, + "spans": [ + [ + "Sitting", + 0.0, + 1.54 + ], + [ + "curled", + 1.54, + 2.44 + ], + [ + "up", + 2.44, + 2.995 + ], + [ + "in", + 3.22, + 3.89 + ], + [ + "myself", + 3.89, + 5.22 + ] + ], + "pins": [ + { + "t": "Sitting", + "pin": 0, + "cut": null + }, + { + "t": "curled", + "pin": 1, + "cut": null + }, + { + "t": "up", + "pin": 2, + "cut": null + }, + { + "t": "in", + "pin": 3, + "cut": null + }, + { + "t": "myself", + "pin": 4, + "cut": null + } + ], "beats": 11.0, "renders": { - "lead": 5.735, - "8ve-a": 5.735, - "8ve-b": 5.735, - "low3": 5.735, - "low5": 5.735 + "lead": 5.755 }, "snaps": [ "up -20ms", @@ -163,20 +333,40 @@ "in +80ms", "myself +30ms" ], "trims": [ - "up \u2212400ms" + "up \u2212225ms" ], "words": "sitting curled up in myself" }, "w-i-think": { "slice": "f-i-think", - "lead_in": 0.02, + "lead_in": 0.04, + "spans": [ + [ + "I", + 0.0, + 0.8 + ], + [ + "think", + 0.8, + 1.32 + ] + ], + "pins": [ + { + "t": "I", + "pin": 0, + "cut": null + }, + { + "t": "think", + "pin": 1, + "cut": null + } + ], "beats": 3.5, "renders": { - "lead": 2.225, - "8ve-a": 2.225, - "8ve-b": 2.225, - "low3": 2.225, - "low5": 2.225 + "lead": 2.245 }, "snaps": [ "think +160ms" @@ -187,13 +377,43 @@ }, "w-of-a-stone": { "slice": "f-of-a-stone", "lead_in": 0.0, + "spans": [ + [ + "of", + 0.0, + 1.58 + ], + [ + "a", + 1.58, + 2.38 + ], + [ + "stone", + 2.38, + 3.16 + ] + ], + "pins": [ + { + "t": "of", + "pin": 0, + "cut": null + }, + { + "t": "a", + "pin": 1, + "cut": null + }, + { + "t": "stone", + "pin": 2, + "cut": null + } + ], "beats": 8.0, "renders": { - "lead": 4.095, - "8ve-a": 4.095, - "8ve-b": 4.095, - "low3": 4.095, - "low5": 4.095 + "lead": 4.095 }, "snaps": [ "a -40ms", @@ -204,72 +424,220 @@ "words": "of a stone" }, "w-just-waiting": { "slice": "f-just-waiting", - "lead_in": 0.075, + "lead_in": 0.15, + "spans": [ + [ + "Just", + 0.0, + 1.33 + ], + [ + "waiting", + 1.655, + 2.94 + ] + ], + "pins": [ + { + "t": "Just", + "pin": 0, + "cut": null + }, + { + "t": "waiting", + "pin": 1, + "cut": null + } + ], "beats": 6.5, "renders": { - "lead": 3.71, - "8ve-a": 3.71, - "8ve-b": 3.71, - "low3": 3.71, - "low5": 3.71 + "lead": 3.785 }, "snaps": [ "waiting +195ms" ], "trims": [ - "Just \u2212340ms" + "Just \u2212325ms" ], "words": "just waiting" }, "w-very-patiently": { "slice": "f-very-patiently", "lead_in": 0.0, + "spans": [ + [ + "very", + 0.0, + 1.64 + ], + [ + "patiently", + 1.64, + 2.92 + ] + ], + "pins": [ + { + "t": "very", + "pin": 0, + "cut": null + }, + { + "t": "patiently", + "pin": 1, + "cut": null + } + ], "beats": 8.5, "renders": { - "lead": 5.435, - "8ve-a": 5.435, - "8ve-b": 5.435, - "low3": 5.435, - "low5": 5.435 + "lead": 5.435 }, "snaps": [ "patiently +240ms" ], - "trims": [ - "very \u2212520ms" - ], + "trims": [], "words": "very patiently" }, "w-for-time-to-pass": { "slice": "f-for-time-to-pass", - "lead_in": 0.035, + "lead_in": 0.07, + "spans": [ + [ + "for", + 0.0, + 0.865 + ], + [ + "time", + 0.865, + 1.985 + ], + [ + "to", + 1.985, + 3.66 + ], + [ + "pass", + 3.81, + 5.7 + ] + ], + "pins": [ + { + "t": "for", + "pin": 0, + "cut": null + }, + { + "t": "time", + "pin": 1, + "cut": null + }, + { + "t": "to", + "pin": 2, + "cut": null + }, + { + "t": "pass", + "pin": 3, + "cut": null + } + ], "beats": 12.5, "renders": { - "lead": 6.695, - "8ve-a": 6.695, - "8ve-b": 6.695, - "low3": 6.695, - "low5": 6.695 + "lead": 6.73 }, "snaps": [ "time +245ms", "to -75ms" ], "trims": [ - "to \u2212185ms" + "to \u2212180ms" ], "words": "for time to pass" }, "w-n-getting-curled": { "slice": "n-getting-curled", "lead_in": 0.0, + "spans": [ + [ + "getting", + 0.0, + 0.725 + ], + [ + "curled", + 0.725, + 1.825 + ], + [ + "up", + 1.825, + 1.905 + ], + [ + "in", + 1.905, + 2.72 + ], + [ + "myself", + 2.72, + 3.89 + ], + [ + "i", + 3.89, + 4.865 + ], + [ + "think", + 4.865, + 5.1 + ] + ], + "pins": [ + { + "t": "getting", + "pin": 0, + "cut": null + }, + { + "t": "curled", + "pin": 1, + "cut": null + }, + { + "t": "up", + "pin": 2, + "cut": null + }, + { + "t": "in", + "pin": 3, + "cut": null + }, + { + "t": "myself", + "pin": 4, + "cut": null + }, + { + "t": "i", + "pin": 5, + "cut": null + }, + { + "t": "think", + "pin": 6, + "cut": null + } + ], "beats": 11.0, "renders": { - "lead": 5.635, - "8ve-a": 5.635, - "8ve-b": 5.635, - "low3": 5.635, - "low5": 5.635 + "lead": 5.635 }, "snaps": [ "curled -55ms", @@ -279,21 +647,79 @@ "myself -40ms", "i -110ms", "think +85ms" ], - "trims": [ - "i \u2212165ms" - ], + "trims": [], "words": "getting curled up in myself i think" }, "w-n-stone-waiting": { "slice": "n-stone-waiting", "lead_in": 0.0, + "spans": [ + [ + "A", + 0.0, + 0.915 + ], + [ + "stone", + 0.915, + 1.845 + ], + [ + "just", + 1.845, + 3.715 + ], + [ + "waiting", + 3.715, + 5.65 + ], + [ + "very", + 5.65, + 7.06 + ], + [ + "patiently", + 7.06, + 8.04 + ] + ], + "pins": [ + { + "t": "A", + "pin": 0, + "cut": null + }, + { + "t": "stone", + "pin": 1, + "cut": null + }, + { + "t": "just", + "pin": 2, + "cut": null + }, + { + "t": "waiting", + "pin": 3, + "cut": null + }, + { + "t": "very", + "pin": 4, + "cut": null + }, + { + "t": "patiently", + "pin": 5, + "cut": null + } + ], "beats": 17.0, "renders": { - "lead": 8.59, - "8ve-a": 8.59, - "8ve-b": 8.59, - "low3": 8.59, - "low5": 8.59 + "lead": 8.59 }, "snaps": [ "stone +155ms", @@ -302,23 +728,59 @@ "waiting -225ms", "very +230ms", "patiently +200ms" ], - "trims": [ - "A \u2212215ms", - "just \u2212265ms", - "very \u2212400ms" - ], + "trims": [], "words": "of a stone just waiting very patiently" }, "w-n-for-time-to-pass": { "slice": "n-for-time-to-pass", "lead_in": 0.0, + "spans": [ + [ + "the", + 0.0, + 0.36 + ], + [ + "time", + 0.36, + 1.1 + ], + [ + "to", + 1.1, + 2.69 + ], + [ + "pass", + 2.69, + 3.56 + ] + ], + "pins": [ + { + "t": "the", + "pin": 0, + "cut": null + }, + { + "t": "time", + "pin": 1, + "cut": null + }, + { + "t": "to", + "pin": 2, + "cut": null + }, + { + "t": "pass", + "pin": 3, + "cut": null + } + ], "beats": 5.5, "renders": { - "lead": 3.13, - "8ve-a": 3.13, - "8ve-b": 3.13, - "low3": 3.13, - "low5": 3.13 + "lead": 3.13 }, "snaps": [ "time +200ms", @@ -326,5 +788,2190 @@ "pass +50ms" ], "trims": [], "words": "for time to pass" + }, + "w-rq": { + "slice": "rq-line", + "lead_in": 0.43, + "spans": [ + [ + "sitting\u00b7a", + 0.37, + 1.615 + ], + [ + "sitting\u00b7b", + 1.615, + 1.845 + ], + [ + "curled", + 2.015, + 3.86 + ], + [ + "up", + 4.03, + 4.345 + ], + [ + "in", + 4.515, + 5.14 + ], + [ + "my", + 5.31, + 6.09 + ], + [ + "self", + 6.09, + 7.02 + ], + [ + "i", + 7.19, + 7.605 + ], + [ + "think", + 7.775, + 8.8 + ], + [ + "of", + 8.97, + 9.865 + ], + [ + "a", + 10.035, + 10.66 + ], + [ + "stone", + 10.83, + 13.25 + ], + [ + "just", + 13.42, + 15.035 + ], + [ + "wait", + 15.205, + 16.16 + ], + [ + "ing", + 16.16, + 16.88 + ], + [ + "ve", + 17.05, + 18.495 + ], + [ + "ry", + 18.495, + 18.765 + ], + [ + "pa", + 18.935, + 19.8 + ], + [ + "tient", + 19.8, + 20.34 + ], + [ + "ly", + 20.34, + 21.21 + ], + [ + "for", + 21.38, + 22.105 + ], + [ + "time", + 22.275, + 24.39 + ], + [ + "to", + 24.56, + 25.205 + ], + [ + "pass", + 25.375, + 26.975 + ] + ], + "pins": [ + { + "t": "sitting\u00b7a", + "pin": 0, + "cut": null + }, + { + "t": "sitting\u00b7b", + "pin": 0, + "cut": 1 + }, + { + "t": "curled", + "pin": 1, + "cut": null + }, + { + "t": "up", + "pin": 2, + "cut": null + }, + { + "t": "in", + "pin": 3, + "cut": null + }, + { + "t": "my", + "pin": 4, + "cut": null + }, + { + "t": "self", + "pin": 4, + "cut": 1 + }, + { + "t": "i", + "pin": 5, + "cut": null + }, + { + "t": "think", + "pin": 6, + "cut": null + }, + { + "t": "of", + "pin": 7, + "cut": null + }, + { + "t": "a", + "pin": 8, + "cut": null + }, + { + "t": "stone", + "pin": 9, + "cut": null + }, + { + "t": "just", + "pin": 10, + "cut": null + }, + { + "t": "wait", + "pin": 11, + "cut": null + }, + { + "t": "ing", + "pin": 11, + "cut": 1 + }, + { + "t": "ve", + "pin": 12, + "cut": null + }, + { + "t": "ry", + "pin": 12, + "cut": 1 + }, + { + "t": "pa", + "pin": 13, + "cut": null + }, + { + "t": "tient", + "pin": 13, + "cut": 1 + }, + { + "t": "ly", + "pin": 13, + "cut": 2 + }, + { + "t": "for", + "pin": 14, + "cut": null + }, + { + "t": "time", + "pin": 15, + "cut": null + }, + { + "t": "to", + "pin": 16, + "cut": null + }, + { + "t": "pass", + "pin": 17, + "cut": null + } + ], + "beats": 60.0, + "renders": { + "lead": 30.34 + }, + "snaps": [], + "trims": [ + "sitting\u00b7b \u2212200ms", + "curled \u2212200ms", + "up \u2212200ms", + "in \u2212200ms", + "self \u2212200ms", + "i \u2212200ms", + "think \u2212200ms", + "of \u2212200ms", + "a \u2212200ms", + "stone \u2212200ms", + "just \u2212200ms", + "ing \u2212200ms", + "ry \u2212200ms", + "ly \u2212200ms", + "for \u2212200ms", + "time \u2212200ms", + "to \u2212200ms" + ], + "words": "the whole lyric, assembled from corpus" + }, + "w-sh": { + "slice": "sh-line", + "lead_in": 0.84, + "spans": [ + [ + "sitting\u00b7a", + 0.37, + 1.48 + ], + [ + "sitting\u00b7b", + 1.48, + 2.095 + ], + [ + "curled", + 2.265, + 3.84 + ], + [ + "up", + 4.01, + 4.56 + ], + [ + "in", + 4.73, + 5.45 + ], + [ + "my", + 5.62, + 6.98 + ], + [ + "self", + 6.98, + 7.245 + ], + [ + "i", + 7.415, + 7.785 + ], + [ + "think", + 7.955, + 8.995 + ], + [ + "of", + 9.165, + 9.875 + ], + [ + "a", + 10.045, + 10.46 + ], + [ + "stone", + 10.63, + 12.765 + ], + [ + "just", + 12.935, + 14.605 + ], + [ + "wait", + 14.775, + 15.08 + ], + [ + "ing", + 15.08, + 16.575 + ], + [ + "ve", + 16.745, + 17.765 + ], + [ + "ry", + 17.765, + 18.0 + ], + [ + "pa", + 18.17, + 18.535 + ], + [ + "tient", + 18.535, + 19.815 + ], + [ + "ly", + 19.815, + 20.67 + ], + [ + "for", + 20.84, + 21.835 + ], + [ + "time", + 22.005, + 23.325 + ], + [ + "to", + 23.495, + 24.675 + ], + [ + "pass", + 24.845, + 26.975 + ] + ], + "pins": [ + { + "t": "sitting\u00b7a", + "pin": 0, + "cut": null + }, + { + "t": "sitting\u00b7b", + "pin": 0, + "cut": 1 + }, + { + "t": "curled", + "pin": 1, + "cut": null + }, + { + "t": "up", + "pin": 2, + "cut": null + }, + { + "t": "in", + "pin": 3, + "cut": null + }, + { + "t": "my", + "pin": 4, + "cut": null + }, + { + "t": "self", + "pin": 4, + "cut": 1 + }, + { + "t": "i", + "pin": 5, + "cut": null + }, + { + "t": "think", + "pin": 6, + "cut": null + }, + { + "t": "of", + "pin": 7, + "cut": null + }, + { + "t": "a", + "pin": 8, + "cut": null + }, + { + "t": "stone", + "pin": 9, + "cut": null + }, + { + "t": "just", + "pin": 10, + "cut": null + }, + { + "t": "wait", + "pin": 11, + "cut": null + }, + { + "t": "ing", + "pin": 11, + "cut": 1 + }, + { + "t": "ve", + "pin": 12, + "cut": null + }, + { + "t": "ry", + "pin": 12, + "cut": 1 + }, + { + "t": "pa", + "pin": 13, + "cut": null + }, + { + "t": "tient", + "pin": 13, + "cut": 1 + }, + { + "t": "ly", + "pin": 13, + "cut": 2 + }, + { + "t": "for", + "pin": 14, + "cut": null + }, + { + "t": "time", + "pin": 15, + "cut": null + }, + { + "t": "to", + "pin": 16, + "cut": null + }, + { + "t": "pass", + "pin": 17, + "cut": null + } + ], + "beats": 60.0, + "renders": { + "lead": 30.75 + }, + "snaps": [], + "trims": [ + "sitting\u00b7b \u2212200ms", + "curled \u2212200ms", + "up \u2212200ms", + "in \u2212200ms", + "self \u2212200ms", + "i \u2212200ms", + "think \u2212200ms", + "of \u2212200ms", + "a \u2212200ms", + "stone \u2212200ms", + "just \u2212200ms", + "ing \u2212200ms", + "ry \u2212200ms", + "ly \u2212200ms", + "for \u2212200ms", + "time \u2212200ms", + "to \u2212200ms" + ], + "words": "the whole lyric, assembled from corpus" + }, + "w-lg": { + "slice": "lg-line", + "lead_in": 0.575, + "spans": [ + [ + "sitting\u00b7a", + 0.37, + 1.345 + ], + [ + "sitting\u00b7b", + 1.345, + 2.025 + ], + [ + "curled", + 2.195, + 3.71 + ], + [ + "up", + 3.88, + 4.495 + ], + [ + "in", + 4.665, + 5.335 + ], + [ + "my", + 5.505, + 7.005 + ], + [ + "self", + 7.005, + 7.3 + ], + [ + "i", + 7.47, + 7.75 + ], + [ + "think", + 7.915, + 8.855 + ], + [ + "of", + 9.025, + 9.985 + ], + [ + "a", + 10.155, + 10.725 + ], + [ + "stone", + 10.895, + 13.455 + ], + [ + "just", + 13.66, + 15.105 + ], + [ + "wait", + 15.275, + 16.19 + ], + [ + "ing", + 16.19, + 17.08 + ], + [ + "ve", + 17.25, + 18.36 + ], + [ + "ry", + 18.36, + 18.575 + ], + [ + "pa", + 18.745, + 19.645 + ], + [ + "tient", + 19.645, + 20.245 + ], + [ + "ly", + 20.245, + 21.035 + ], + [ + "for", + 21.205, + 22.255 + ], + [ + "time", + 22.425, + 23.7 + ], + [ + "to", + 23.87, + 24.91 + ], + [ + "pass", + 25.08, + 26.81 + ] + ], + "pins": [ + { + "t": "sitting\u00b7a", + "pin": 0, + "cut": null + }, + { + "t": "sitting\u00b7b", + "pin": 0, + "cut": 1 + }, + { + "t": "curled", + "pin": 1, + "cut": null + }, + { + "t": "up", + "pin": 2, + "cut": null + }, + { + "t": "in", + "pin": 3, + "cut": null + }, + { + "t": "my", + "pin": 4, + "cut": null + }, + { + "t": "self", + "pin": 4, + "cut": 1 + }, + { + "t": "i", + "pin": 5, + "cut": null + }, + { + "t": "think", + "pin": 6, + "cut": null + }, + { + "t": "of", + "pin": 7, + "cut": null + }, + { + "t": "a", + "pin": 8, + "cut": null + }, + { + "t": "stone", + "pin": 9, + "cut": null + }, + { + "t": "just", + "pin": 10, + "cut": null + }, + { + "t": "wait", + "pin": 11, + "cut": null + }, + { + "t": "ing", + "pin": 11, + "cut": 1 + }, + { + "t": "ve", + "pin": 12, + "cut": null + }, + { + "t": "ry", + "pin": 12, + "cut": 1 + }, + { + "t": "pa", + "pin": 13, + "cut": null + }, + { + "t": "tient", + "pin": 13, + "cut": 1 + }, + { + "t": "ly", + "pin": 13, + "cut": 2 + }, + { + "t": "for", + "pin": 14, + "cut": null + }, + { + "t": "time", + "pin": 15, + "cut": null + }, + { + "t": "to", + "pin": 16, + "cut": null + }, + { + "t": "pass", + "pin": 17, + "cut": null + } + ], + "beats": 60.0, + "renders": { + "lead": 30.485 + }, + "snaps": [], + "trims": [ + "sitting\u00b7b \u2212200ms", + "curled \u2212200ms", + "up \u2212200ms", + "in \u2212200ms", + "self \u2212200ms", + "i \u2212195ms", + "think \u2212200ms", + "of \u2212200ms", + "a \u2212200ms", + "stone \u2212205ms", + "just \u2212200ms", + "ing \u2212200ms", + "ry \u2212200ms", + "ly \u2212200ms", + "for \u2212200ms", + "time \u2212200ms", + "to \u2212200ms" + ], + "words": "the whole lyric, assembled from corpus" + }, + "w-pf": { + "slice": "pf-line", + "lead_in": 0.765, + "spans": [ + [ + "sitting\u00b7a", + 0.37, + 0.945 + ], + [ + "sitting\u00b7b", + 0.945, + 2.015 + ], + [ + "curled", + 2.185, + 3.765 + ], + [ + "up", + 3.935, + 4.54 + ], + [ + "in", + 4.71, + 5.425 + ], + [ + "my", + 5.595, + 6.395 + ], + [ + "self", + 6.395, + 7.165 + ], + [ + "i", + 7.37, + 7.62 + ], + [ + "think", + 7.79, + 8.915 + ], + [ + "of", + 9.085, + 9.905 + ], + [ + "a", + 10.075, + 10.48 + ], + [ + "stone", + 10.65, + 12.705 + ], + [ + "just", + 12.88, + 14.23 + ], + [ + "wait", + 14.4, + 14.635 + ], + [ + "ing", + 14.635, + 16.005 + ], + [ + "ve", + 16.175, + 17.26 + ], + [ + "ry", + 17.26, + 17.505 + ], + [ + "pa", + 17.675, + 18.095 + ], + [ + "tient", + 18.095, + 19.375 + ], + [ + "ly", + 19.375, + 20.225 + ], + [ + "for", + 20.395, + 21.39 + ], + [ + "time", + 21.56, + 22.88 + ], + [ + "to", + 23.05, + 24.105 + ], + [ + "pass", + 24.305, + 26.53 + ] + ], + "pins": [ + { + "t": "sitting\u00b7a", + "pin": 0, + "cut": null + }, + { + "t": "sitting\u00b7b", + "pin": 0, + "cut": 1 + }, + { + "t": "curled", + "pin": 1, + "cut": null + }, + { + "t": "up", + "pin": 2, + "cut": null + }, + { + "t": "in", + "pin": 3, + "cut": null + }, + { + "t": "my", + "pin": 4, + "cut": null + }, + { + "t": "self", + "pin": 4, + "cut": 1 + }, + { + "t": "i", + "pin": 5, + "cut": null + }, + { + "t": "think", + "pin": 6, + "cut": null + }, + { + "t": "of", + "pin": 7, + "cut": null + }, + { + "t": "a", + "pin": 8, + "cut": null + }, + { + "t": "stone", + "pin": 9, + "cut": null + }, + { + "t": "just", + "pin": 10, + "cut": null + }, + { + "t": "wait", + "pin": 11, + "cut": null + }, + { + "t": "ing", + "pin": 11, + "cut": 1 + }, + { + "t": "ve", + "pin": 12, + "cut": null + }, + { + "t": "ry", + "pin": 12, + "cut": 1 + }, + { + "t": "pa", + "pin": 13, + "cut": null + }, + { + "t": "tient", + "pin": 13, + "cut": 1 + }, + { + "t": "ly", + "pin": 13, + "cut": 2 + }, + { + "t": "for", + "pin": 14, + "cut": null + }, + { + "t": "time", + "pin": 15, + "cut": null + }, + { + "t": "to", + "pin": 16, + "cut": null + }, + { + "t": "pass", + "pin": 17, + "cut": null + } + ], + "beats": 60.0, + "renders": { + "lead": 30.675 + }, + "snaps": [], + "trims": [ + "sitting\u00b7b \u2212200ms", + "curled \u2212200ms", + "up \u2212200ms", + "in \u2212200ms", + "self \u2212205ms", + "i \u2212200ms", + "think \u2212200ms", + "of \u2212200ms", + "a \u2212200ms", + "stone \u2212205ms", + "just \u2212200ms", + "ing \u2212200ms", + "ry \u2212200ms", + "ly \u2212200ms", + "for \u2212200ms", + "time \u2212200ms", + "to \u2212200ms" + ], + "words": "the whole lyric, assembled from corpus" + }, + "w-rd": { + "slice": "rd-line", + "lead_in": 0.405, + "spans": [ + [ + "sitting\u00b7a", + 0.37, + 1.665 + ], + [ + "sitting\u00b7b", + 1.665, + 2.09 + ], + [ + "curled", + 2.255, + 3.765 + ], + [ + "up", + 3.935, + 4.555 + ], + [ + "in", + 4.725, + 5.175 + ], + [ + "my", + 5.345, + 6.605 + ], + [ + "self", + 6.605, + 6.98 + ], + [ + "i", + 7.18, + 7.445 + ], + [ + "think", + 7.615, + 8.385 + ], + [ + "of", + 8.555, + 9.41 + ], + [ + "a", + 9.58, + 9.84 + ], + [ + "stone", + 10.01, + 11.68 + ], + [ + "just", + 11.85, + 13.12 + ], + [ + "wait", + 13.29, + 13.675 + ], + [ + "ing", + 13.675, + 15.37 + ], + [ + "ve", + 15.54, + 16.315 + ], + [ + "ry", + 16.315, + 16.745 + ], + [ + "pa", + 16.915, + 18.03 + ], + [ + "tient", + 18.03, + 18.62 + ], + [ + "ly", + 18.62, + 19.65 + ], + [ + "for", + 19.82, + 20.725 + ], + [ + "time", + 20.89, + 22.19 + ], + [ + "to", + 22.36, + 23.17 + ], + [ + "pass", + 23.37, + 24.505 + ] + ], + "pins": [ + { + "t": "sitting\u00b7a", + "pin": 0, + "cut": null + }, + { + "t": "sitting\u00b7b", + "pin": 0, + "cut": 1 + }, + { + "t": "curled", + "pin": 1, + "cut": null + }, + { + "t": "up", + "pin": 2, + "cut": null + }, + { + "t": "in", + "pin": 3, + "cut": null + }, + { + "t": "my", + "pin": 4, + "cut": null + }, + { + "t": "self", + "pin": 4, + "cut": 1 + }, + { + "t": "i", + "pin": 5, + "cut": null + }, + { + "t": "think", + "pin": 6, + "cut": null + }, + { + "t": "of", + "pin": 7, + "cut": null + }, + { + "t": "a", + "pin": 8, + "cut": null + }, + { + "t": "stone", + "pin": 9, + "cut": null + }, + { + "t": "just", + "pin": 10, + "cut": null + }, + { + "t": "wait", + "pin": 11, + "cut": null + }, + { + "t": "ing", + "pin": 11, + "cut": 1 + }, + { + "t": "ve", + "pin": 12, + "cut": null + }, + { + "t": "ry", + "pin": 12, + "cut": 1 + }, + { + "t": "pa", + "pin": 13, + "cut": null + }, + { + "t": "tient", + "pin": 13, + "cut": 1 + }, + { + "t": "ly", + "pin": 13, + "cut": 2 + }, + { + "t": "for", + "pin": 14, + "cut": null + }, + { + "t": "time", + "pin": 15, + "cut": null + }, + { + "t": "to", + "pin": 16, + "cut": null + }, + { + "t": "pass", + "pin": 17, + "cut": null + } + ], + "beats": 60.0, + "renders": { + "lead": 30.315 + }, + "snaps": [], + "trims": [ + "sitting\u00b7b \u2212195ms", + "curled \u2212200ms", + "up \u2212200ms", + "in \u2212200ms", + "self \u2212200ms", + "i \u2212200ms", + "think \u2212200ms", + "of \u2212200ms", + "a \u2212200ms", + "stone \u2212200ms", + "just \u2212200ms", + "ing \u2212200ms", + "ry \u2212200ms", + "ly \u2212200ms", + "for \u2212195ms", + "time \u2212200ms", + "to \u2212200ms" + ], + "words": "the whole lyric, assembled from corpus" + }, + "w-cp": { + "slice": "cp-line", + "lead_in": 0.43, + "spans": [ + [ + "sitting\u00b7a", + 0.37, + 0.825 + ], + [ + "sitting\u00b7b", + 0.825, + 1.35 + ], + [ + "curled", + 1.52, + 2.58 + ], + [ + "up", + 2.75, + 3.2 + ], + [ + "in", + 3.37, + 3.695 + ], + [ + "my", + 3.865, + 4.845 + ], + [ + "self", + 4.845, + 5.055 + ], + [ + "i", + 5.225, + 5.625 + ], + [ + "think", + 5.795, + 6.57 + ], + [ + "of", + 6.74, + 7.885 + ], + [ + "a", + 8.055, + 8.505 + ], + [ + "stone", + 8.675, + 9.36 + ], + [ + "just", + 9.53, + 10.755 + ], + [ + "wait", + 10.925, + 11.58 + ], + [ + "ing", + 11.635, + 13.44 + ], + [ + "ve", + 13.64, + 14.35 + ], + [ + "ry", + 14.35, + 14.495 + ], + [ + "pa", + 14.665, + 15.67 + ], + [ + "tient", + 15.67, + 16.875 + ], + [ + "ly", + 16.875, + 17.48 + ], + [ + "for", + 17.65, + 18.435 + ], + [ + "time", + 18.605, + 19.82 + ], + [ + "to", + 19.99, + 20.71 + ], + [ + "pass", + 20.88, + 22.06 + ] + ], + "pins": [ + { + "t": "sitting\u00b7a", + "pin": 0, + "cut": null + }, + { + "t": "sitting\u00b7b", + "pin": 0, + "cut": 1 + }, + { + "t": "curled", + "pin": 1, + "cut": null + }, + { + "t": "up", + "pin": 2, + "cut": null + }, + { + "t": "in", + "pin": 3, + "cut": null + }, + { + "t": "my", + "pin": 4, + "cut": null + }, + { + "t": "self", + "pin": 4, + "cut": 1 + }, + { + "t": "i", + "pin": 5, + "cut": null + }, + { + "t": "think", + "pin": 6, + "cut": null + }, + { + "t": "of", + "pin": 7, + "cut": null + }, + { + "t": "a", + "pin": 8, + "cut": null + }, + { + "t": "stone", + "pin": 9, + "cut": null + }, + { + "t": "just", + "pin": 10, + "cut": null + }, + { + "t": "wait", + "pin": 11, + "cut": null + }, + { + "t": "ing", + "pin": 11, + "cut": 1 + }, + { + "t": "ve", + "pin": 12, + "cut": null + }, + { + "t": "ry", + "pin": 12, + "cut": 1 + }, + { + "t": "pa", + "pin": 13, + "cut": null + }, + { + "t": "tient", + "pin": 13, + "cut": 1 + }, + { + "t": "ly", + "pin": 13, + "cut": 2 + }, + { + "t": "for", + "pin": 14, + "cut": null + }, + { + "t": "time", + "pin": 15, + "cut": null + }, + { + "t": "to", + "pin": 16, + "cut": null + }, + { + "t": "pass", + "pin": 17, + "cut": null + } + ], + "beats": 60.0, + "renders": { + "lead": 30.34 + }, + "snaps": [], + "trims": [ + "sitting\u00b7b \u2212200ms", + "curled \u2212200ms", + "up \u2212200ms", + "in \u2212200ms", + "self \u2212200ms", + "i \u2212200ms", + "think \u2212200ms", + "of \u2212200ms", + "a \u2212200ms", + "stone \u2212200ms", + "just \u2212200ms", + "wait \u221285ms", + "ing \u2212200ms", + "ry \u2212200ms", + "ly \u2212200ms", + "for \u2212200ms", + "time \u2212200ms", + "to \u2212200ms" + ], + "words": "the whole lyric, assembled from corpus" + }, + "w-s": { + "slice": "s-line", + "lead_in": 0.37, + "spans": [ + [ + "sitting\u00b7a", + 0.37, + 0.665 + ], + [ + "sitting\u00b7b", + 0.665, + 2.005 + ], + [ + "curled", + 2.175, + 3.615 + ], + [ + "up", + 3.815, + 4.375 + ], + [ + "in", + 4.54, + 5.105 + ], + [ + "my", + 5.275, + 6.145 + ], + [ + "self", + 6.145, + 6.86 + ], + [ + "i", + 7.03, + 7.275 + ], + [ + "think", + 7.445, + 8.505 + ], + [ + "of", + 8.675, + 9.39 + ], + [ + "a", + 9.56, + 10.07 + ], + [ + "stone", + 10.24, + 12.215 + ], + [ + "just", + 12.385, + 13.5 + ], + [ + "wait", + 13.67, + 14.375 + ], + [ + "ing", + 14.375, + 15.705 + ], + [ + "ve", + 15.875, + 16.13 + ], + [ + "ry", + 16.13, + 16.92 + ], + [ + "pa", + 17.085, + 17.595 + ], + [ + "tient", + 17.595, + 18.375 + ], + [ + "ly", + 18.375, + 19.92 + ], + [ + "for", + 20.09, + 20.965 + ], + [ + "time", + 21.13, + 22.61 + ], + [ + "to", + 22.78, + 24.075 + ], + [ + "pass", + 24.245, + 25.34 + ] + ], + "pins": [ + { + "t": "sitting\u00b7a", + "pin": 0, + "cut": null + }, + { + "t": "sitting\u00b7b", + "pin": 0, + "cut": 1 + }, + { + "t": "curled", + "pin": 1, + "cut": null + }, + { + "t": "up", + "pin": 2, + "cut": null + }, + { + "t": "in", + "pin": 3, + "cut": null + }, + { + "t": "my", + "pin": 4, + "cut": null + }, + { + "t": "self", + "pin": 4, + "cut": 1 + }, + { + "t": "i", + "pin": 5, + "cut": null + }, + { + "t": "think", + "pin": 6, + "cut": null + }, + { + "t": "of", + "pin": 7, + "cut": null + }, + { + "t": "a", + "pin": 8, + "cut": null + }, + { + "t": "stone", + "pin": 9, + "cut": null + }, + { + "t": "just", + "pin": 10, + "cut": null + }, + { + "t": "wait", + "pin": 11, + "cut": null + }, + { + "t": "ing", + "pin": 11, + "cut": 1 + }, + { + "t": "ve", + "pin": 12, + "cut": null + }, + { + "t": "ry", + "pin": 12, + "cut": 1 + }, + { + "t": "pa", + "pin": 13, + "cut": null + }, + { + "t": "tient", + "pin": 13, + "cut": 1 + }, + { + "t": "ly", + "pin": 13, + "cut": 2 + }, + { + "t": "for", + "pin": 14, + "cut": null + }, + { + "t": "time", + "pin": 15, + "cut": null + }, + { + "t": "to", + "pin": 16, + "cut": null + }, + { + "t": "pass", + "pin": 17, + "cut": null + } + ], + "beats": 60.0, + "renders": { + "lead": 30.28 + }, + "snaps": [], + "trims": [ + "sitting\u00b7b \u2212200ms", + "curled \u2212200ms", + "up \u2212195ms", + "in \u2212200ms", + "self \u2212200ms", + "i \u2212200ms", + "think \u2212200ms", + "of \u2212200ms", + "a \u2212200ms", + "stone \u2212200ms", + "just \u2212200ms", + "ing \u2212200ms", + "ry \u2212195ms", + "ly \u2212200ms", + "for \u2212195ms", + "time \u2212200ms", + "to \u2212200ms" + ], + "words": "the whole lyric, assembled from corpus" + }, + "w-o": { + "slice": "o-line", + "lead_in": 0.55, + "spans": [ + [ + "sitting\u00b7a", + 0.37, + 1.445 + ], + [ + "sitting\u00b7b", + 1.445, + 1.805 + ], + [ + "curled", + 1.975, + 3.2 + ], + [ + "up", + 3.37, + 4.165 + ], + [ + "in", + 4.335, + 4.93 + ], + [ + "my", + 5.1, + 5.875 + ], + [ + "self", + 5.875, + 6.77 + ], + [ + "i", + 6.94, + 7.665 + ], + [ + "think", + 7.835, + 8.725 + ], + [ + "of", + 8.895, + 9.665 + ], + [ + "a", + 9.835, + 10.255 + ], + [ + "stone", + 10.455, + 12.16 + ], + [ + "just", + 12.33, + 14.515 + ], + [ + "wait", + 14.685, + 15.895 + ], + [ + "ing", + 15.895, + 16.3 + ], + [ + "ve", + 16.47, + 17.675 + ], + [ + "ry", + 17.675, + 18.055 + ], + [ + "pa", + 18.22, + 20.06 + ], + [ + "tient", + 20.06, + 20.67 + ], + [ + "ly", + 20.67, + 21.15 + ], + [ + "for", + 21.32, + 22.43 + ], + [ + "time", + 22.6, + 23.985 + ], + [ + "to", + 24.155, + 24.905 + ], + [ + "pass", + 25.075, + 26.59 + ] + ], + "pins": [ + { + "t": "sitting\u00b7a", + "pin": 0, + "cut": null + }, + { + "t": "sitting\u00b7b", + "pin": 0, + "cut": 1 + }, + { + "t": "curled", + "pin": 1, + "cut": null + }, + { + "t": "up", + "pin": 2, + "cut": null + }, + { + "t": "in", + "pin": 3, + "cut": null + }, + { + "t": "my", + "pin": 4, + "cut": null + }, + { + "t": "self", + "pin": 4, + "cut": 1 + }, + { + "t": "i", + "pin": 5, + "cut": null + }, + { + "t": "think", + "pin": 6, + "cut": null + }, + { + "t": "of", + "pin": 7, + "cut": null + }, + { + "t": "a", + "pin": 8, + "cut": null + }, + { + "t": "stone", + "pin": 9, + "cut": null + }, + { + "t": "just", + "pin": 10, + "cut": null + }, + { + "t": "wait", + "pin": 11, + "cut": null + }, + { + "t": "ing", + "pin": 11, + "cut": 1 + }, + { + "t": "ve", + "pin": 12, + "cut": null + }, + { + "t": "ry", + "pin": 12, + "cut": 1 + }, + { + "t": "pa", + "pin": 13, + "cut": null + }, + { + "t": "tient", + "pin": 13, + "cut": 1 + }, + { + "t": "ly", + "pin": 13, + "cut": 2 + }, + { + "t": "for", + "pin": 14, + "cut": null + }, + { + "t": "time", + "pin": 15, + "cut": null + }, + { + "t": "to", + "pin": 16, + "cut": null + }, + { + "t": "pass", + "pin": 17, + "cut": null + } + ], + "beats": 60.0, + "renders": { + "lead": 30.46 + }, + "snaps": [], + "trims": [ + "sitting\u00b7b \u2212200ms", + "curled \u2212200ms", + "up \u2212200ms", + "in \u2212200ms", + "self \u2212200ms", + "i \u2212200ms", + "think \u2212200ms", + "of \u2212200ms", + "a \u2212200ms", + "stone \u2212200ms", + "just \u2212200ms", + "ing \u2212200ms", + "ry \u2212195ms", + "ly \u2212200ms", + "for \u2212200ms", + "time \u2212200ms", + "to \u2212200ms" + ], + "words": "the whole lyric, assembled from corpus" } } \ No newline at end of file diff --git a/pop/loner/vox4/.wizard.json b/pop/loner/vox4/.wizard.json new file mode 100644 --- /dev/null +++ b/pop/loner/vox4/.wizard.json @@ -0,0 +1,1 @@ +{"lane": "loner", "bpm": 122.0, "tonic": 237.0, "frame_s": 0.005, "phrases": {"w-whole-line": {"slice": "f-whole-line", "wav": "/Users/jas/aesthetic-computer/pop/loner/samples/f-whole-line.wav", "sr": 48000, "leadIn": 0.04, "beats": 60.0, "units": [{"t": "sitting\u00b7a", "beat": 0.0, "dur": 2.0, "st": 7, "src0": 0.0, "src1": 0.755}, {"t": "sitting\u00b7b", "beat": 2.0, "dur": 2.0, "st": 5, "src0": 0.755, "src1": 1.51}, {"t": "curled", "beat": 4.0, "dur": 1.91, "st": 3, "src0": 1.51, "src1": 2.4}, {"t": "up", "beat": 5.91, "dur": 2.09, "st": 2, "src0": 2.4, "src1": 2.995}, {"t": "in", "beat": 8.0, "dur": 2.0, "st": 0, "src0": 3.22, "src1": 3.89}, {"t": "my", "beat": 10.0, "dur": 1.5, "st": 5, "src0": 3.89, "src1": 4.5}, {"t": "self", "beat": 11.5, "dur": 2.5, "st": 2, "src0": 4.5, "src1": 5.5}, {"t": "i", "beat": 14.0, "dur": 2.0, "st": -2, "src0": 5.5, "src1": 6.215}, {"t": "think", "beat": 16.0, "dur": 2.0, "st": -5, "src0": 6.215, "src1": 7.15}, {"t": "of", "beat": 18.0, "dur": 4.0, "st": 12, "src0": 7.15, "src1": 8.76}, {"t": "a", "beat": 22.0, "dur": 1.75, "st": 10, "src0": 8.76, "src1": 9.19}, {"t": "stone", "beat": 23.75, "dur": 4.25, "st": 5, "src0": 9.19, "src1": 10.52}, {"t": "just", "beat": 28.0, "dur": 4.0, "st": 2, "src0": 11.065, "src1": 12.425}, {"t": "wait", "beat": 32.0, "dur": 2.0, "st": 3, "src0": 12.67, "src1": 13.7}, {"t": "ing", "beat": 34.0, "dur": 2.0, "st": 2, "src0": 13.7, "src1": 14.4}, {"t": "ve", "beat": 36.0, "dur": 2.0, "st": 0, "src0": 14.4, "src1": 15.17}, {"t": "ry", "beat": 38.0, "dur": 2.0, "st": -2, "src0": 15.17, "src1": 15.9}, {"t": "pa", "beat": 40.0, "dur": 2.0, "st": 7, "src0": 15.9, "src1": 16.655}, {"t": "tient", "beat": 42.0, "dur": 2.0, "st": 5, "src0": 16.655, "src1": 17.7}, {"t": "ly", "beat": 44.0, "dur": 2.0, "st": 3, "src0": 17.7, "src1": 18.54}, {"t": "for", "beat": 46.0, "dur": 2.0, "st": 5, "src0": 18.54, "src1": 19.315}, {"t": "time", "beat": 48.0, "dur": 4.0, "st": 7, "src0": 19.315, "src1": 20.405}, {"t": "to", "beat": 52.0, "dur": 4.0, "st": 3, "src0": 21.2, "src1": 22.16}, {"t": "pass", "beat": 56.0, "dur": 4.0, "st": 3, "src0": 22.78, "src1": 24.31}], "events": [{"a": 0.05, "b": 0.785, "kind": "NOTE", "st": 6.86}, {"a": 0.785, "b": 1.5, "kind": "NOTE", "st": 4.8}, {"a": 1.585, "b": 2.69, "kind": "NOTE", "st": 2.73}, {"a": 3.19, "b": 3.81, "kind": "NOTE", "st": 0.01}, {"a": 3.81, "b": 3.935, "kind": "NOTE", "st": 1.32}, {"a": 3.935, "b": 4.47, "kind": "NOTE", "st": 5.16}, {"a": 4.47, "b": 4.73, "kind": "FRIC", "st": null}, {"a": 4.74, "b": 5.175, "kind": "NOTE", "st": 2.15}, {"a": 5.485, "b": 6.11, "kind": "NOTE", "st": -2.0}, {"a": 6.3, "b": 6.545, "kind": "NOTE", "st": -4.86}, {"a": 7.18, "b": 8.685, "kind": "NOTE", "st": 11.89}, {"a": 8.78, "b": 9.145, "kind": "NOTE", "st": 10.34}, {"a": 9.265, "b": 9.475, "kind": "FRIC", "st": null}, {"a": 9.565, "b": 10.465, "kind": "NOTE", "st": 5.06}, {"a": 11.11, "b": 11.235, "kind": "FRIC", "st": null}, {"a": 11.235, "b": 11.975, "kind": "NOTE", "st": 2.16}, {"a": 12.73, "b": 14.450000000000001, "kind": "NOTE", "st": 2.68}, {"a": 14.450000000000001, "b": 15.165000000000001, "kind": "NOTE", "st": 0.03}, {"a": 15.165000000000001, "b": 15.44, "kind": "NOTE", "st": -2.0}, {"a": 15.92, "b": 16.045, "kind": "NOTE", "st": 6.45}, {"a": 16.045, "b": 16.615000000000002, "kind": "NOTE", "st": 7.22}, {"a": 16.615000000000002, "b": 16.830000000000002, "kind": "FRIC", "st": null}, {"a": 16.845, "b": 17.16, "kind": "NOTE", "st": 5.09}, {"a": 17.66, "b": 18.365000000000002, "kind": "NOTE", "st": 2.94}, {"a": 18.53, "b": 19.225, "kind": "NOTE", "st": 5.2}, {"a": 19.315, "b": 19.45, "kind": "PUFF", "st": null}, {"a": 19.48, "b": 20.345, "kind": "NOTE", "st": 7.14}, {"a": 21.11, "b": 21.215, "kind": "FRIC", "st": null}, {"a": 21.245, "b": 22.1, "kind": "NOTE", "st": 3.06}, {"a": 22.825, "b": 22.985, "kind": "PUFF", "st": null}, {"a": 22.985, "b": 23.92, "kind": "NOTE", "st": 3.02}], "frames": {"st": [null, null, null, null, 10.04, 8.1, 5.35, 4.44, 3.1, 6.53, 7.52, 8.09, 7.97, 7.52, 7.32, 7.25, 7.3, 7.23, 7.23, 7.21, 7.24, 7.21, 7.18, 7.12, 7.09, 7.02, 7.0, 6.94, 6.96, 6.9, 6.9, 6.95, 6.94, 6.94, 6.96, 6.98, 6.99, 6.98, 6.99, 6.99, 7.01, 6.98, 6.97, 6.99, 6.96, 6.95, 6.92, 6.97, 6.95, 6.96, 6.96, 7.0, 6.96, 6.99, 6.98, 6.96, 6.95, 6.99, 6.95, 6.96, 6.99, 6.93, 6.97, 6.96, 6.96, 6.96, 6.89, 6.89, 6.91, 6.88, 6.84, 6.83, 6.87, 6.86, 6.83, 6.87, 6.85, 6.87, 6.84, 6.88, 6.86, 6.86, 6.86, 6.89, 6.88, 6.92, 6.89, 6.88, 6.87, 6.84, 6.86, 6.88, 6.83, 6.84, 6.82, 6.83, 6.8, 6.81, 6.83, 6.81, 6.78, 6.78, 6.82, 6.8, 6.8, 6.79, 6.73, 6.75, 6.77, 6.71, 6.76, 6.78, 6.76, 6.77, 6.78, 6.8, 6.77, 6.77, 6.78, 6.79, 6.75, 6.77, 6.73, 6.75, 6.74, 6.74, 6.75, 6.72, 6.73, 6.76, 6.74, 6.7, 6.73, 6.75, 6.73, 6.69, 6.7, 6.73, 6.73, 6.72, 6.69, 6.73, 6.72, 6.68, 6.68, 6.66, 6.54, 6.51, 6.42, 6.3, 5.83, 6.21, 6.25, 5.98, 6.3, 6.25, 6.6, 6.7, 6.55, 6.56, 6.84, 6.6, 6.91, 6.37, 5.69, 5.29, 4.98, 5.11, 5.08, 4.95, 4.94, 4.89, 4.87, 4.85, 4.87, 4.82, 4.92, 4.94, 4.94, 4.96, 4.92, 4.95, 5.04, 5.05, 5.07, 5.1, 5.08, 5.11, 5.1, 5.15, 5.14, 5.13, 5.09, 5.08, 5.1, 5.05, 5.03, 5.11, 5.04, 5.06, 5.02, 5.06, 4.98, 5.01, 5.03, 4.98, 4.93, 4.95, 4.99, 4.9, 4.91, 4.87, 4.88, 4.88, 4.89, 4.83, 4.83, 4.84, 4.86, 4.79, 4.83, 4.79, 4.81, 4.79, 4.76, 4.78, 4.76, 4.8, 4.72, 4.81, 4.75, 4.72, 4.72, 4.69, 4.66, 4.67, 4.68, 4.68, 4.72, 4.79, 4.76, 4.76, 4.78, 4.78, 4.78, 4.81, 4.8, 4.81, 4.79, 4.78, 4.76, 4.74, 4.8, 4.79, 4.76, 4.73, 4.78, 4.76, 4.79, 4.71, 4.76, 4.8, 4.76, 4.75, 4.77, 4.76, 4.8, 4.73, 4.74, 4.76, 4.84, 4.75, 4.77, 4.78, 4.76, 4.73, 4.73, 4.78, 4.71, 4.81, 4.76, 4.79, 4.78, 4.77, 4.79, 4.75, 4.76, 4.67, 4.67, 4.65, 4.68, 4.59, 4.51, 4.39, 4.41, 4.35, 4.37, 4.3, 4.48, 4.49, 4.29, 3.95, 2.3, 2.5, -3.74, -10.62, -10.77, -11.85, -13.03, -13.72, -10.15, -6.95, -2.78, -7.07, -1.97, -1.91, -1.98, 0.31, -0.17, 2.61, 1.37, 2.4, 1.49, 2.33, 1.97, 1.95, 2.42, 2.38, 2.47, 2.44, 2.41, 2.35, 2.47, 2.59, 2.53, 2.54, 2.63, 2.6, 2.56, 2.56, 2.58, 2.56, 2.63, 2.63, 2.66, 2.7, 2.69, 2.71, 2.73, 2.75, 2.71, 2.77, 2.77, 2.78, 2.77, 2.77, 2.77, 2.79, 2.79, 2.75, 2.73, 2.75, 2.77, 2.74, 2.72, 2.77, 2.74, 2.72, 2.73, 2.73, 2.76, 2.74, 2.78, 2.78, 2.78, 2.78, 2.82, 2.85, 2.85, 2.85, 2.83, 2.84, 2.85, 2.8, 2.81, 2.8, 2.76, 2.76, 2.79, 2.79, 2.78, 2.75, 2.78, 2.81, 2.78, 2.77, 2.78, 2.79, 2.75, 2.82, 2.79, 2.79, 2.78, 2.79, 2.76, 2.75, 2.79, 2.76, 2.78, 2.76, 2.77, 2.8, 2.79, 2.78, 2.81, 2.83, 2.86, 2.81, 2.79, 2.8, 2.82, 2.76, 2.78, 2.76, 2.8, 2.76, 2.79, 2.79, 2.78, 2.81, 2.81, 2.79, 2.81, 2.84, 2.87, 2.83, 2.85, 2.84, 2.89, 2.88, 2.88, 2.88, 2.91, 2.92, 2.9, 2.91, 2.95, 2.94, 2.96, 2.89, 2.91, 2.88, 2.85, 2.81, 2.81, 2.83, 2.8, 2.82, 2.82, 2.77, 2.79, 2.73, 2.75, 2.72, 2.69, 2.7, 2.69, 2.73, 2.71, 2.72, 2.75, 2.72, 2.71, 2.71, 2.66, 2.64, 2.64, 2.63, 2.56, 2.43, 2.32, 2.3, 2.26, 2.31, 2.21, 2.23, 2.14, 2.04, 2.34, 2.69, 2.7, 2.5, 2.41, 2.26, 2.23, 2.19, 2.13, 2.06, 2.11, 1.95, 1.95, 1.98, 1.96, 1.92, 1.92, 1.92, 1.89, 1.9, 1.92, 1.91, 1.9, 1.94, 1.98, 2.03, 2.0, 2.05, 2.05, 2.06, 2.06, 2.09, 2.15, 2.08, 2.08, 2.05, 2.11, 2.02, 2.08, 2.0, 1.97, 1.92, 1.64, 0.96, 1.2, 1.55, -0.76, 2.3, 1.88, 1.86, 2.64, 2.33, 1.71, 1.85, 2.0, 2.1, 1.85, 1.64, 1.51, 1.65, 1.14, 2.32, 1.38, 3.45, 2.85, 1.52, 1.92, 1.1, 1.04, 1.82, -3.05, -6.06, -6.37, -3.8, -4.61, -4.82, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, -1.99, -2.19, 0.9, -0.08, 3.17, 4.12, 3.17, 1.18, 3.85, 0.27, 0.01, 0.24, 0.13, 0.16, 0.16, 0.11, 0.06, 0.04, 0.01, -0.04, 0.0, -0.03, -0.11, -0.17, -0.18, -0.1, -0.13, -0.15, -0.17, -0.12, -0.19, -0.2, -0.22, -0.19, -0.2, -0.22, -0.17, -0.15, -0.18, -0.06, -0.14, -0.1, -0.11, -0.07, -0.03, -0.06, -0.06, 0.0, -0.01, 0.03, 0.01, 0.09, 0.04, 0.04, -0.02, -0.01, -0.1, -0.14, -0.53, -0.62, -0.57, -0.5, -0.55, -0.43, -0.31, -0.25, -0.22, -0.25, -0.18, -0.04, -0.12, -0.15, -0.02, -0.2, 0.04, -0.11, 0.01, -0.02, 0.01, 0.0, 0.0, 0.12, 0.03, 0.01, 0.11, 0.02, 0.06, 0.01, 0.1, 0.06, 0.01, 0.03, -0.04, 0.01, 0.03, 0.03, 0.01, -0.02, -0.09, 0.04, -0.11, 0.05, 0.02, 0.12, -0.04, 0.11, 0.05, 0.14, 0.02, 0.06, 0.02, 0.03, 0.12, -0.01, 0.06, 0.16, 0.01, 0.04, 0.07, 0.17, 0.09, 0.11, 0.21, 0.18, 0.24, 0.19, 0.28, 0.31, 0.36, 0.35, 0.43, 0.51, 0.57, 0.61, 0.63, 0.77, 0.78, 0.9, 0.91, 0.91, 1.23, 1.14, 1.32, 1.76, 2.38, 3.45, 2.49, 2.27, 2.56, 2.61, 2.95, 3.65, 5.59, 4.83, 4.97, 5.07, 5.05, 5.25, 5.44, 5.36, 5.32, 5.58, 5.5, 5.5, 5.35, 5.4, 5.44, 5.35, 5.33, 5.34, 5.3, 5.25, 5.26, 5.21, 5.21, 5.21, 5.17, 5.17, 5.13, 5.13, 5.1, 5.11, 5.14, 5.14, 5.15, 5.18, 5.2, 5.14, 5.2, 5.17, 5.16, 5.16, 5.17, 5.15, 5.16, 5.15, 5.17, 5.16, 5.17, 5.12, 5.12, 5.15, 5.12, 5.15, 5.13, 5.1, 5.18, 5.11, 5.14, 5.18, 5.11, 5.14, 5.19, 5.17, 5.14, 5.16, 5.16, 5.19, 5.17, 5.18, 5.13, 5.14, 5.12, 5.09, 5.11, 5.08, 5.06, 5.03, 5.07, 5.03, 5.04, 4.98, 4.97, 4.98, 4.98, 5.02, 5.01, 5.01, 5.02, 5.05, 5.1, 5.08, 5.15, 5.13, 5.19, 5.2, 5.21, 5.25, 5.26, 5.28, 5.24, 5.32, 5.33, 5.33, 5.26, 5.28, 5.23, 5.2, 5.18, 5.11, 5.12, 5.07, 4.99, 4.86, 4.76, 4.67, 4.71, 4.62, 4.53, 4.44, 4.16, 4.36, 3.85, 3.9, 4.88, 4.39, 4.2, 4.41, 5.95, 4.8, 4.23, 4.88, 4.82, 4.58, 5.12, 5.2, 4.93, 4.94, 6.72, 5.0, 4.92, 6.43, 4.12, 4.4, 4.02, 8.65, 6.11, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, -0.33, 1.34, 3.69, 3.08, 3.21, 3.35, 3.38, 2.9, 2.67, 2.45, 2.31, 2.32, 2.27, 2.2, 2.17, 2.21, 2.19, 2.15, 2.19, 2.18, 2.25, 2.26, 2.25, 2.3, 2.3, 2.27, 2.28, 2.29, 2.22, 2.26, 2.21, 2.26, 2.21, 2.23, 2.21, 2.2, 2.21, 2.24, 2.22, 2.21, 2.16, 2.17, 2.12, 2.08, 2.09, 2.06, 2.08, 2.08, 2.06, 2.06, 2.04, 2.05, 2.04, 2.0, 2.01, 1.97, 2.0, 1.98, 1.93, 1.97, 1.98, 2.03, 2.01, 1.96, 2.0, 2.01, 2.06, 2.05, 2.04, 2.06, 2.04, 2.12, 2.11, 2.12, 2.17, 2.2, 2.21, 2.2, 2.2, 2.21, 2.15, 2.12, 2.06, 2.01, 1.95, 1.96, 2.15, 2.12, 2.12, 2.02, 1.88, 2.15, 2.23, 1.75, 2.43, 2.05, 1.85, 2.16, 2.12, 1.78, 2.23, 2.39, 2.13, 0.94, 2.06, 1.63, 1.89, 1.32, 2.26, 2.35, 2.84, 1.96, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, -20.62, -20.43, -20.37, -20.25, -20.66, -19.5, -18.77, -18.25, -17.17, -17.03, -17.65, -11.95, -5.51, -4.75, 1.85, 3.32, 4.03, 1.17, 1.55, 0.61, -0.75, -1.76, -1.85, -2.0, -1.94, -2.01, -2.1, -2.05, -2.05, -2.11, -2.11, -2.11, -2.19, -2.17, -2.17, -2.19, -2.22, -2.14, -2.12, -2.08, -2.11, -2.11, -2.08, -2.14, -2.11, -2.15, -2.14, -2.16, -2.1, -2.13, -2.14, -2.1, -2.08, -2.13, -2.0, -1.97, -1.93, -1.96, -1.84, -1.92, -1.81, -1.71, -1.72, -1.71, -1.74, -1.72, -1.71, -1.72, -1.71, -1.75, -1.77, -1.82, -1.76, -1.84, -1.86, -1.87, -1.95, -1.97, -1.95, -1.98, -2.0, -2.07, -2.1, -2.01, -2.0, -2.01, -2.01, -2.0, -1.97, -1.97, -2.07, -2.09, -2.09, -2.13, -2.07, -2.11, -2.17, -2.25, -2.2, -2.22, -2.15, -2.28, -2.22, -2.13, -2.21, -2.13, -2.15, -2.12, -2.09, -2.11, -2.01, -1.98, -1.97, -2.0, -1.96, -1.97, -1.94, -2.03, -1.99, -1.97, -2.04, -1.9, -2.01, -1.86, -1.75, -1.89, -1.83, -1.88, -1.94, -1.91, -1.85, -1.96, -1.9, -1.96, -1.93, -1.81, -1.74, -1.81, -1.83, -1.82, -2.34, -1.92, -1.96, -0.95, -0.52, -2.02, -0.8, -1.14, -2.02, -2.29, -1.18, -2.04, -1.77, -2.67, -0.02, -1.78, -1.82, 0.1, -1.12, -1.78, -1.41, -1.91, -3.41, -0.88, -3.95, -3.48, -5.48, -3.72, -8.11, -5.42, -6.1, -9.33, -3.59, -4.45, -2.87, -5.84, -7.0, -5.88, -6.31, -5.87, -5.08, -2.62, -2.2, -6.84, -3.72, -6.32, -5.41, -5.64, -5.32, -5.28, -5.41, -5.37, -5.37, -5.32, -5.4, -5.32, -5.21, -5.22, -5.11, -5.06, -4.93, -4.9, -4.89, -4.83, -4.86, -4.75, -4.73, -4.77, -4.78, -4.65, -4.58, -4.78, -4.79, -4.81, -4.76, -4.79, -5.08, -4.79, -4.63, -4.69, -5.06, -4.82, -4.81, -4.57, -4.7, -4.57, -4.85, -5.32, -5.14, -5.55, -5.0, -5.21, -4.87, -4.81, -4.47, -5.19, -3.7, -7.09, -7.26, -5.9, -6.17, -5.91, -8.81, -3.83, -3.98, -1.97, -0.48, -3.73, -0.92, -3.04, -8.87, -10.44, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, -10.79, -8.72, -8.15, -9.01, -9.77, -13.96, -17.14, -16.38, -16.22, -18.67, -19.02, -18.95, -19.14, -19.02, -18.58, -17.67, -17.58, -17.09, -10.97, -10.1, -10.25, -9.86, -12.89, -12.22, -11.36, -6.7, -6.4, -6.45, -5.66, -3.98, -6.87, -5.5, -6.05, -5.95, -7.91, -8.57, -6.04, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, -19.36, -19.36, -19.23, -19.37, -19.3, -18.95, -17.97, -16.24, -15.81, -18.42, -22.47, -21.68, -20.38, -18.49, -16.44, -17.43, -20.98, -21.5, -19.48, -8.54, 4.84, 12.84, 13.31, 13.48, 13.08, 14.57, 11.39, 12.09, 12.3, 12.03, 12.06, 12.27, 12.22, 12.28, 12.37, 12.38, 12.35, 12.33, 12.27, 12.26, 12.23, 12.17, 12.15, 12.06, 12.08, 12.06, 12.02, 12.02, 12.0, 11.94, 11.92, 11.89, 11.87, 11.84, 11.81, 11.83, 11.88, 11.92, 11.86, 11.9, 11.93, 11.88, 11.87, 11.91, 11.92, 11.9, 11.89, 11.89, 11.88, 11.88, 11.9, 11.96, 12.0, 12.01, 11.97, 12.01, 12.02, 11.91, 11.91, 11.91, 11.88, 11.86, 11.85, 11.87, 11.89, 11.87, 11.86, 11.88, 11.88, 11.91, 11.88, 11.94, 11.91, 11.93, 11.97, 11.97, 11.89, 11.87, 11.9, 11.95, 11.87, 11.85, 11.87, 11.84, 11.84, 11.84, 11.86, 11.84, 11.82, 11.82, 11.76, 11.85, 11.79, 11.77, 11.72, 11.73, 11.75, 11.72, 11.82, 11.76, 11.77, 11.76, 11.66, 11.76, 11.88, 11.89, 11.83, 11.81, 11.96, 11.88, 11.96, 11.96, 11.94, 11.81, 11.93, 11.93, 11.9, 12.01, 11.89, 12.03, 11.97, 11.91, 11.95, 11.89, 11.96, 11.99, 11.96, 12.0, 11.97, 11.88, 11.87, 11.95, 11.92, 11.87, 11.87, 11.9, 11.92, 11.89, 11.96, 11.97, 11.91, 11.88, 11.96, 12.02, 11.99, 12.02, 11.98, 11.96, 11.98, 11.89, 11.87, 11.97, 11.88, 11.98, 12.02, 12.02, 12.1, 11.98, 12.1, 12.13, 12.06, 11.98, 11.95, 11.91, 12.07, 11.94, 11.92, 11.95, 11.99, 11.92, 11.99, 12.0, 11.97, 12.01, 12.02, 11.92, 12.05, 12.02, 11.93, 12.08, 12.0, 12.04, 11.95, 11.94, 12.03, 11.98, 11.99, 11.94, 11.85, 11.76, 11.91, 11.82, 11.85, 11.87, 11.88, 11.82, 11.87, 11.81, 11.85, 11.88, 11.77, 11.85, 11.89, 11.87, 11.92, 11.86, 11.91, 11.87, 11.8, 11.83, 11.85, 11.86, 11.89, 11.84, 11.84, 11.81, 11.78, 11.88, 11.84, 11.72, 11.79, 11.79, 11.73, 11.87, 11.86, 11.79, 11.87, 11.84, 11.88, 11.89, 11.81, 11.88, 11.85, 11.83, 11.93, 12.08, 11.96, 11.88, 11.87, 11.97, 11.83, 11.81, 11.86, 11.84, 11.81, 11.79, 11.93, 11.73, 11.74, 11.82, 11.74, 11.78, 11.79, 11.81, 11.86, 11.78, 11.91, 11.83, 11.8, 11.82, 11.82, 11.83, 11.87, 11.86, 11.77, 11.91, 11.96, 11.95, 12.01, 11.87, 11.91, 11.87, 11.85, 11.89, 11.89, 11.89, 11.84, 11.97, 11.82, 11.83, 11.83, 11.84, 11.91, 11.88, 11.79, 11.81, 11.83, 11.92, 11.84, 11.85, 11.8, 11.89, 11.82, 11.73, 11.92, 11.88, 11.87, 11.87, 11.76, 11.81, 11.83, 11.65, 11.75, 11.58, 11.84, 11.65, 11.89, 11.83, 11.77, 11.9, 11.6, 11.77, 12.12, 11.82, 11.88, 12.17, 12.39, 11.81, 11.65, 11.64, 11.78, 13.15, 8.78, 11.65, 12.93, 11.18, 10.9, 10.75, 10.55, 10.61, 10.54, 10.49, 10.51, 10.45, 10.4, 10.36, 10.37, 10.33, 10.27, 10.31, 10.22, 10.23, 10.29, 10.34, 10.34, 10.44, 10.43, 10.48, 10.49, 10.48, 10.48, 10.51, 10.47, 10.48, 10.48, 10.43, 10.46, 10.39, 10.43, 10.41, 10.38, 10.38, 10.31, 10.32, 10.27, 10.29, 10.25, 10.25, 10.25, 10.16, 10.15, 10.22, 10.13, 10.14, 10.12, 10.05, 10.04, 10.04, 9.95, 10.11, 10.05, 10.11, 10.22, 10.25, 10.12, 10.2, 10.31, 10.25, 10.28, 10.09, 10.15, 10.21, 10.37, 10.43, 10.54, 10.37, 10.61, 10.48, 10.9, 10.49, 10.94, 10.53, 10.45, 10.5, 10.09, 9.84, 9.98, 9.85, 9.88, 10.59, 10.09, 10.6, 12.64, 11.62, 12.27, 9.34, 11.71, 10.25, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, -14.12, -13.99, -13.05, -11.36, -7.27, -9.26, -11.38, -11.39, -11.01, null, null, null, null, null, null, null, null, null, null, 0.04, 0.81, 6.13, 5.43, 6.67, 7.01, 6.13, 5.93, 5.85, 5.66, 5.58, 5.57, 5.55, 5.59, 5.53, 5.47, 5.47, 5.46, 5.44, 5.34, 5.34, 5.3, 5.28, 5.26, 5.26, 5.24, 5.26, 5.18, 5.2, 5.15, 5.16, 5.11, 5.14, 5.06, 5.13, 5.13, 5.13, 5.1, 5.13, 5.1, 5.09, 5.07, 5.09, 5.08, 5.06, 5.07, 5.06, 5.06, 5.05, 5.12, 5.08, 5.12, 5.11, 5.08, 5.16, 5.09, 5.09, 5.06, 5.06, 5.04, 4.99, 5.0, 5.0, 5.01, 5.02, 4.99, 5.03, 5.03, 5.03, 5.04, 4.97, 5.0, 4.95, 4.98, 4.93, 4.98, 4.94, 4.91, 4.95, 4.92, 4.91, 4.93, 4.91, 4.9, 4.95, 4.94, 4.88, 4.94, 4.92, 4.94, 4.92, 4.9, 4.89, 4.89, 4.87, 4.94, 4.97, 4.96, 4.95, 4.96, 4.98, 4.97, 5.0, 4.92, 4.94, 4.92, 4.93, 4.93, 4.93, 4.93, 4.9, 4.97, 4.93, 5.0, 4.99, 4.99, 5.03, 5.01, 5.08, 5.05, 5.04, 5.05, 5.04, 5.03, 4.96, 4.98, 4.99, 5.07, 4.99, 4.97, 4.99, 4.97, 5.01, 5.02, 4.96, 5.02, 5.07, 5.09, 4.98, 5.02, 5.13, 4.99, 4.86, 4.99, 5.11, 5.1, 5.05, 5.11, 5.1, 5.18, 5.15, 5.13, 5.23, 5.23, 5.25, 5.17, 5.21, 5.24, 5.26, 5.2, 5.19, 5.15, 5.16, 5.23, 5.18, 5.11, 5.08, 5.19, 5.06, 5.19, 5.12, 5.12, 5.23, 5.14, 4.97, 5.25, 5.08, 5.02, 4.93, 5.12, 5.75, 4.42, 4.78, 5.09, 5.29, 4.66, 5.72, 4.68, 1.76, 3.18, 1.88, 2.14, -2.25, -6.52, -16.58, -15.88, -15.02, -13.44, -17.87, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, -21.07, -20.41, -18.55, -14.16, -12.37, -13.13, null, null, null, null, -15.12, -16.62, -17.93, -20.34, -20.47, -20.14, -18.63, -17.44, -16.3, -18.57, -21.57, null, null, null, null, null, -20.22, -16.85, -11.57, -12.87, -14.22, -17.79, -19.56, -19.47, -18.73, -18.44, -18.22, -19.16, -19.61, null, null, null, null, null, null, -13.91, -14.4, -8.04, -7.31, -8.24, -2.42, -5.24, -3.27, -2.73, -1.21, -2.6, -4.45, -3.46, 0.15, 2.12, 2.55, 1.84, 0.63, 1.5, 1.79, 2.47, 2.49, 2.22, 2.14, 2.17, 2.08, 2.07, 2.02, 2.07, 2.08, 2.05, 2.08, 2.05, 2.12, 2.14, 2.12, 2.2, 2.25, 2.3, 2.38, 2.42, 2.54, 2.59, 2.6, 2.62, 2.61, 2.59, 2.6, 2.61, 2.58, 2.56, 2.55, 2.53, 2.51, 2.53, 2.48, 2.53, 2.5, 2.48, 2.44, 2.35, 2.24, 2.24, 2.16, 2.15, 2.1, 2.14, 2.17, 2.15, 2.13, 2.12, 2.1, 2.13, 2.11, 2.07, 2.1, 2.1, 2.11, 2.12, 2.14, 2.2, 2.15, 2.22, 2.23, 2.22, 2.22, 2.22, 2.22, 2.22, 2.18, 2.28, 2.24, 2.26, 2.24, 2.33, 2.26, 2.31, 2.27, 2.25, 2.28, 2.28, 2.24, 2.23, 2.23, 2.23, 2.24, 2.19, 2.18, 2.2, 2.19, 2.2, 2.17, 2.18, 2.2, 2.19, 2.16, 2.18, 2.16, 2.16, 2.14, 2.13, 2.12, 2.11, 2.11, 2.1, 2.1, 2.09, 2.08, 2.1, 2.14, 2.1, 2.11, 2.11, 2.14, 2.14, 2.13, 2.16, 2.13, 2.13, 2.1, 2.17, 2.1, 2.1, 2.15, 2.15, 2.16, 2.11, 2.16, 2.13, 2.14, 2.12, 2.1, 2.11, 2.11, 2.08, 2.13, 2.12, 2.08, 2.16, 2.16, 2.12, 2.17, 2.16, 2.13, 2.09, 2.04, 2.02, 2.13, 2.17, 2.11, 2.12, 2.57, 2.64, 2.11, 1.92, 2.15, 2.2, 2.47, 2.13, 1.82, 2.23, 2.03, 2.03, 1.62, 1.32, 0.77, 1.89, 2.13, 2.43, 0.51, 2.55, -1.75, 1.97, 2.25, -0.33, 1.57, 2.1, 2.19, 1.66, 2.63, -1.36, -2.5, -8.62, -15.35, -20.26, -21.44, -22.81, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, -22.12, -20.36, -20.37, -20.17, -20.64, -20.58, -20.07, -19.83, -18.41, -17.41, -17.6, -20.97, -21.89, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, -13.02, -6.22, -7.65, -6.88, -7.65, -10.87, -13.76, -12.36, -10.61, -7.23, -3.43, 1.73, 4.14, 2.12, 0.8, 3.46, 2.49, 1.47, 2.83, 3.04, 3.07, 3.12, 2.83, 2.5, 2.18, 2.29, 2.4, 2.45, 2.55, 2.48, 2.53, 2.59, 2.53, 2.62, 2.63, 2.7, 2.82, 2.93, 2.91, 2.94, 2.86, 2.88, 2.95, 3.05, 2.96, 3.01, 3.03, 3.05, 2.95, 2.97, 2.88, 2.91, 2.86, 2.85, 2.79, 2.79, 2.8, 2.8, 2.76, 2.81, 2.79, 2.83, 2.88, 2.86, 2.9, 2.91, 2.88, 2.93, 2.95, 2.91, 2.88, 2.85, 2.88, 2.9, 2.9, 2.88, 2.92, 2.93, 2.95, 2.89, 2.9, 2.92, 2.91, 2.92, 2.97, 2.95, 2.99, 3.0, 3.0, 3.01, 2.98, 3.03, 2.98, 3.0, 3.04, 3.06, 3.04, 3.12, 3.13, 3.19, 3.08, 3.03, 3.03, 3.07, 3.02, 3.06, 3.03, 3.11, 3.08, 3.14, 3.16, 3.15, 3.09, 3.1, 3.09, 3.11, 3.03, 3.02, 2.99, 2.97, 3.03, 3.0, 3.03, 3.06, 3.02, 3.08, 3.02, 3.04, 3.01, 3.03, 2.99, 3.04, 3.0, 3.04, 3.01, 3.03, 3.04, 3.02, 2.99, 2.97, 2.95, 2.99, 2.98, 2.96, 3.0, 2.94, 2.95, 2.93, 2.97, 2.98, 3.0, 2.94, 2.95, 2.98, 2.92, 2.91, 2.91, 2.94, 2.9, 2.89, 2.96, 2.99, 2.93, 2.98, 2.93, 2.95, 3.0, 3.06, 2.99, 3.0, 3.02, 2.96, 2.87, 2.93, 2.95, 3.03, 3.02, 2.94, 2.99, 2.97, 2.98, 2.98, 2.93, 2.94, 2.94, 2.98, 2.96, 2.94, 2.93, 2.97, 2.87, 2.81, 2.79, 2.79, 2.74, 2.67, 2.47, 0.77, 1.04, 1.96, 2.49, 2.68, 3.69, 2.68, 2.89, 4.13, 4.17, 2.97, 2.75, 2.46, 2.23, 2.25, 2.2, 2.17, 2.2, 2.15, 2.08, 2.02, 1.97, 2.02, 1.94, 1.93, 1.91, 1.95, 2.05, 2.02, 2.05, 2.06, 2.06, 2.0, 2.05, 2.15, 2.09, 2.08, 2.05, 2.03, 2.01, 2.06, 2.02, 2.02, 1.95, 2.04, 2.03, 2.02, 2.07, 2.01, 2.02, 2.03, 1.96, 2.04, 2.01, 2.0, 1.99, 2.04, 2.05, 2.0, 2.07, 1.96, 2.05, 1.98, 1.92, 1.85, 1.88, 1.74, 1.72, 1.79, 1.79, 1.81, 1.73, 1.78, 1.74, 1.83, 1.8, 1.84, 1.81, 1.88, 1.84, 1.85, 1.9, 1.9, 1.97, 2.04, 1.98, 2.02, 1.99, 1.97, 2.03, 2.0, 2.04, 1.99, 2.08, 2.07, 2.06, 1.91, 2.04, 1.82, 1.9, 1.75, 1.95, 1.78, 1.98, 1.73, 1.78, 1.66, 1.8, 1.93, 1.93, 1.82, 1.9, 1.86, 1.71, 1.83, 1.88, 1.93, 1.85, 1.86, 1.84, 1.68, 1.88, 1.91, 1.8, 1.83, 1.95, 1.88, 1.82, 1.89, 1.84, 1.91, 1.73, 1.99, 1.82, 1.8, 1.78, 2.07, 1.78, 1.8, 1.95, 1.83, 1.97, 1.76, 1.5, 1.88, 1.95, 1.38, 1.45, 1.81, 1.57, 1.46, 1.56, 1.1, 1.17, 1.49, 0.89, 0.79, -0.22, -0.23, 0.9, 1.21, 1.43, 1.44, 1.64, 1.37, 1.19, 1.04, 1.0, 0.9, 0.75, 0.67, 0.57, 0.56, 0.45, 0.34, 0.28, 0.36, 0.19, 0.21, 0.31, 0.2, 0.17, 0.21, 0.15, 0.12, 0.09, 0.02, 0.13, 0.1, 0.08, 0.1, 0.1, 0.13, 0.16, 0.14, 0.12, 0.21, 0.2, 0.17, 0.17, 0.17, 0.24, 0.19, 0.23, 0.23, 0.23, 0.18, 0.26, 0.28, 0.23, 0.21, 0.2, 0.23, 0.18, 0.18, 0.2, 0.2, 0.19, 0.12, 0.17, 0.16, 0.15, 0.11, 0.1, 0.08, 0.07, 0.05, 0.0, -0.01, -0.03, -0.04, -0.02, -0.02, -0.04, -0.07, -0.07, -0.12, -0.13, -0.08, -0.06, -0.03, -0.05, -0.03, -0.02, -0.05, 0.01, -0.02, 0.02, 0.02, 0.01, 0.02, 0.03, 0.03, 0.05, 0.11, -0.0, -0.0, 0.03, 0.02, -0.04, -0.01, -0.03, -0.05, -0.01, -0.04, -0.04, -0.01, -0.05, -0.02, -0.07, -0.09, 0.07, 0.0, -0.04, -0.1, -0.06, -0.06, -0.21, -0.14, -0.18, -0.23, -0.23, -0.23, -0.19, -0.21, -0.19, -0.13, -0.11, -0.03, -0.04, -0.0, 0.05, 0.03, 0.1, 0.03, -0.01, 0.08, 0.06, 0.03, 0.02, 0.1, 0.04, 0.01, -0.01, -0.01, -0.11, -0.13, -0.17, -0.26, -0.3, -0.4, -0.52, -0.55, -0.6, -0.65, -0.77, -0.77, -0.92, -1.09, -1.32, -1.66, -1.66, -1.73, -1.8, -1.89, -2.08, -2.07, -2.11, -2.21, -2.34, -2.4, -2.5, -2.45, -2.44, -2.45, -2.31, -2.29, -2.16, -2.21, -2.2, -2.24, -2.26, -2.3, -2.28, -2.24, -2.22, -2.18, -2.16, -2.11, -2.06, -1.99, -1.93, -2.02, -1.79, -1.75, -1.81, -1.82, -2.0, -1.71, -2.16, -1.79, -1.93, -1.2, -0.47, -1.87, -1.13, -1.51, -1.33, -2.33, -1.23, -2.4, -5.9, -2.29, -2.7, -2.03, -2.05, -1.58, -2.08, -2.08, -2.21, -7.0, -5.52, -10.33, -9.37, -10.46, -14.11, -14.47, -14.16, -14.52, -14.51, -13.12, -14.0, -12.76, -11.41, -13.07, -16.82, -17.11, -17.77, -20.73, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, -1.01, 1.25, 0.78, 0.66, 3.59, 7.43, 6.41, 6.48, 6.45, 6.61, 6.49, 6.45, 7.04, 7.19, 7.16, 7.28, 7.38, 7.49, 7.57, 7.64, 7.54, 7.58, 7.58, 7.62, 7.55, 7.53, 7.54, 7.53, 7.54, 7.58, 7.6, 7.54, 7.56, 7.54, 7.64, 7.63, 7.53, 7.53, 7.48, 7.4, 7.42, 7.36, 7.34, 7.34, 7.34, 7.33, 7.34, 7.3, 7.29, 7.31, 7.36, 7.29, 7.26, 7.27, 7.26, 7.21, 7.24, 7.23, 7.24, 7.21, 7.22, 7.16, 7.21, 7.22, 7.25, 7.21, 7.21, 7.22, 7.21, 7.16, 7.18, 7.18, 7.16, 7.14, 7.16, 7.16, 7.15, 7.14, 7.12, 7.09, 7.14, 7.15, 7.11, 7.13, 7.15, 7.13, 7.11, 7.06, 7.07, 7.07, 7.1, 7.09, 7.09, 7.13, 7.13, 7.13, 7.12, 7.12, 7.1, 7.13, 7.11, 7.13, 7.12, 7.17, 7.1, 7.12, 7.14, 7.1, 7.11, 7.05, 7.06, 7.05, 7.06, 7.1, 7.12, 7.17, 7.2, 7.4, 7.47, 7.49, 7.46, 7.46, 7.49, 7.51, 7.35, 7.34, 7.37, 7.27, 7.01, 7.03, 7.33, 7.25, 7.42, 7.47, 7.69, 7.74, 7.59, 8.1, 8.22, 6.29, 8.61, 8.37, 6.23, 6.67, 8.05, 8.3, 7.79, 8.13, 4.91, 5.96, 6.09, 6.75, 6.36, 4.93, 6.11, 8.64, 8.02, 8.73, null, null, null, null, null, null, null, null, null, null, null, null, 2.04, 5.65, 7.58, 5.56, 5.87, 5.74, 5.09, 5.14, 5.11, 5.13, 5.15, 5.1, 5.07, 5.1, 5.02, 5.02, 5.07, 5.01, 4.98, 4.97, 5.05, 5.03, 5.04, 5.06, 5.01, 5.1, 5.1, 5.07, 5.09, 5.05, 5.07, 5.08, 5.07, 5.09, 5.1, 5.14, 5.11, 5.15, 5.19, 5.16, 5.14, 5.12, 5.14, 5.1, 5.09, 5.02, 4.97, 4.85, 4.84, 4.86, 4.81, 4.88, 4.89, 4.92, 4.9, 4.92, 4.92, 4.97, 4.92, 5.09, 5.22, 5.3, 5.4, 5.36, 5.41, 5.24, 5.27, 5.39, 6.07, 5.53, 5.34, 5.08, 4.45, 5.16, 4.49, 5.2, 4.85, 5.41, 4.75, 5.87, 4.7, 4.81, 4.91, 4.2, 5.17, 3.38, 4.03, 2.71, 2.33, 2.72, -0.98, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, -4.74, -3.42, -3.64, -3.55, -5.39, -4.07, -3.7, -5.99, -2.71, -1.16, -1.33, -3.54, -4.21, -5.71, -5.13, -4.71, 0.59, 2.69, 1.97, 3.64, 2.89, 2.76, 2.31, 2.47, 2.49, 2.35, 2.54, 2.48, 2.52, 2.59, 2.6, 2.51, 2.64, 2.66, 2.62, 2.71, 2.75, 2.71, 2.74, 2.79, 2.78, 2.81, 2.88, 2.91, 2.89, 2.98, 3.02, 3.05, 3.05, 3.04, 3.02, 3.19, 3.11, 3.08, 3.19, 3.12, 3.18, 3.13, 3.04, 3.06, 3.09, 3.02, 3.06, 3.07, 3.06, 3.06, 3.04, 3.04, 3.04, 3.01, 3.0, 2.97, 3.0, 2.97, 2.92, 2.92, 2.91, 2.93, 2.98, 2.91, 3.01, 2.92, 3.01, 2.94, 2.97, 3.04, 2.94, 2.89, 2.89, 2.91, 2.87, 2.89, 2.88, 2.9, 2.98, 3.0, 3.02, 3.07, 3.06, 3.04, 3.0, 3.02, 3.06, 3.0, 2.97, 2.9, 2.94, 2.94, 2.86, 2.85, 2.89, 2.86, 2.79, 2.86, 2.86, 2.86, 2.9, 2.83, 3.0, 3.11, 3.01, 3.08, 3.16, 3.15, 3.19, 3.13, 3.14, 3.12, 3.12, 3.08, 3.05, 2.96, 2.82, 2.81, 3.22, 6.45, 2.97, 3.24, 3.12, 3.19, 2.91, 2.73, 2.75, 2.84, 2.94, 2.81, 2.62, 2.63, 2.67, 2.55, 2.43, 2.34, 3.55, 3.76, 2.47, 2.25, 2.43, 1.43, 2.38, 1.35, 3.59, 2.05, 1.01, 4.77, 3.75, 3.92, 0.68, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 6.49, 3.65, 5.11, 6.21, 5.67, 5.37, 5.25, 5.25, 5.34, 5.32, 5.44, 5.34, 5.37, 5.41, 5.35, 5.32, 5.3, 5.25, 5.26, 5.2, 5.22, 5.18, 5.2, 5.23, 5.19, 5.26, 5.22, 5.24, 5.2, 5.21, 5.2, 5.21, 5.2, 5.27, 5.22, 5.24, 5.2, 5.21, 5.2, 5.2, 5.22, 5.24, 5.15, 5.19, 5.15, 5.19, 5.21, 5.18, 5.16, 5.19, 5.21, 5.22, 5.19, 5.21, 5.2, 5.2, 5.16, 5.18, 5.22, 5.21, 5.22, 5.24, 5.23, 5.26, 5.27, 5.28, 5.25, 5.24, 5.25, 5.2, 5.21, 5.18, 5.22, 5.15, 5.15, 5.13, 5.15, 5.16, 5.14, 5.15, 5.15, 5.14, 5.13, 5.16, 5.17, 5.14, 5.15, 5.14, 5.14, 5.17, 5.14, 5.16, 5.22, 5.15, 5.2, 5.17, 5.2, 5.16, 5.18, 5.22, 5.18, 5.15, 5.22, 5.2, 5.18, 5.2, 5.16, 5.2, 5.22, 5.18, 5.15, 5.22, 5.2, 5.17, 5.17, 5.17, 5.2, 5.21, 5.17, 5.19, 5.2, 5.2, 5.19, 5.21, 5.2, 5.2, 5.18, 5.2, 5.15, 4.99, 4.82, 4.79, 4.85, 4.99, 4.87, 4.7, 4.85, 4.87, 5.09, 5.24, 5.4, 5.25, 5.15, 5.16, 5.37, 5.03, 4.97, 5.03, 5.04, 4.96, 3.99, 5.3, 5.13, 5.52, 5.12, 4.7, 6.81, 5.12, 3.7, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 4.23, 7.29, 6.63, 5.13, 2.71, 4.24, 6.27, 7.44, 7.72, 8.52, 6.46, 6.65, 7.44, 7.08, 7.19, 7.01, 7.16, 7.23, 7.43, 7.47, 7.56, 7.31, 7.32, 7.33, 7.25, 7.26, 7.24, 7.2, 7.2, 7.14, 7.11, 7.08, 7.12, 7.13, 7.14, 7.17, 7.18, 7.2, 7.17, 7.21, 7.17, 7.24, 7.2, 7.23, 7.23, 7.24, 7.23, 7.2, 7.22, 7.23, 7.23, 7.19, 7.19, 7.2, 7.16, 7.19, 7.2, 7.18, 7.15, 7.16, 7.17, 7.16, 7.14, 7.17, 7.17, 7.18, 7.19, 7.18, 7.16, 7.19, 7.2, 7.17, 7.18, 7.17, 7.16, 7.16, 7.16, 7.12, 7.11, 7.12, 7.1, 7.12, 7.12, 7.14, 7.14, 7.13, 7.14, 7.15, 7.17, 7.14, 7.16, 7.15, 7.14, 7.15, 7.12, 7.1, 7.11, 7.09, 7.07, 7.06, 7.06, 7.01, 7.01, 7.02, 6.96, 6.99, 6.95, 6.94, 6.94, 6.94, 6.94, 6.93, 6.93, 6.93, 6.93, 6.93, 6.93, 6.91, 6.96, 6.97, 6.99, 7.02, 7.05, 7.1, 7.09, 7.15, 7.11, 7.14, 7.12, 7.14, 7.11, 7.12, 7.08, 7.06, 7.05, 7.12, 7.14, 7.19, 7.15, 7.13, 7.14, 7.09, 7.05, 7.03, 7.0, 6.99, 6.97, 6.92, 6.91, 6.93, 6.92, 6.92, 6.92, 6.9, 6.93, 6.93, 7.01, 7.02, 7.04, 7.06, 7.1, 7.1, 7.09, 7.1, 7.17, 7.21, 7.16, 7.14, 7.18, 7.22, 7.2, 7.2, 7.37, 7.4, 7.37, 7.32, 7.5, 7.42, 7.35, 7.26, 7.42, 7.4, 7.25, 7.24, 7.26, 6.97, 7.21, 5.91, 7.54, 7.55, 7.65, 5.94, 7.04, 7.31, 6.93, 6.92, 9.1, 6.95, 7.14, 4.97, 0.83, -0.04, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, -21.0, -18.11, -18.54, -19.14, -19.39, -19.95, -20.23, -21.0, null, null, null, null, null, null, null, null, null, null, null, -6.34, -6.49, -7.37, -5.03, -4.23, -0.89, -0.44, 0.73, -1.27, 3.22, 3.06, 2.01, 2.81, 3.03, 3.21, 3.09, 3.11, 3.12, 3.14, 3.09, 3.13, 3.08, 3.03, 3.03, 2.99, 2.99, 2.95, 2.9, 2.92, 2.93, 2.93, 2.9, 2.95, 2.97, 2.98, 3.01, 2.97, 3.05, 3.02, 3.04, 3.06, 3.09, 3.12, 3.05, 3.05, 3.02, 2.98, 3.0, 3.0, 2.96, 2.99, 2.94, 2.97, 2.97, 2.96, 3.01, 2.98, 2.98, 2.98, 3.05, 3.01, 3.07, 3.05, 3.08, 3.03, 3.04, 3.08, 3.08, 3.07, 3.07, 3.13, 3.12, 3.16, 3.21, 3.18, 3.17, 3.18, 3.18, 3.2, 3.14, 3.08, 3.08, 3.04, 3.01, 2.96, 2.97, 2.95, 2.96, 2.93, 2.96, 2.95, 2.99, 2.99, 3.06, 2.99, 2.99, 3.0, 3.0, 2.97, 2.94, 2.95, 2.96, 2.96, 3.02, 3.0, 2.99, 3.06, 3.06, 3.09, 3.07, 3.17, 3.13, 3.09, 3.06, 3.1, 3.1, 3.07, 3.08, 3.05, 3.03, 3.05, 3.06, 3.08, 3.05, 3.11, 3.04, 3.06, 3.03, 3.04, 2.98, 3.07, 2.97, 3.03, 3.06, 3.11, 3.06, 3.03, 3.04, 3.11, 3.03, 3.02, 3.17, 3.07, 2.97, 3.11, 3.02, 3.08, 3.11, 3.07, 3.08, 3.06, 3.17, 3.18, 3.23, 3.2, 3.18, 3.17, 3.18, 3.09, 3.22, 3.16, 3.27, 3.28, 3.26, 3.24, 3.2, 3.18, 3.26, 3.17, 3.43, 3.42, 3.36, 3.26, 3.2, 3.31, 3.3, 3.14, 3.09, 3.2, 3.16, 3.54, 3.07, 2.38, 3.25, 2.93, 2.66, 4.42, 5.24, 2.88, 2.59, 2.38, 2.45, 3.29, -0.95, -9.5, -17.15, -19.75, -20.46, -20.41, -20.3, -19.44, -18.45, -19.65, -20.79, -20.16, -19.12, -19.0, -19.5, -20.17, -21.01, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 1.51, 0.99, 2.85, 2.79, 2.38, 2.08, 2.57, 2.24, 2.61, 2.78, 2.99, 3.17, 3.29, 3.17, 3.24, 3.28, 3.29, 3.39, 3.32, 3.32, 3.29, 3.24, 3.27, 3.18, 3.19, 3.18, 3.18, 3.2, 3.19, 3.16, 3.18, 3.12, 3.15, 3.1, 3.12, 3.1, 3.06, 3.06, 3.06, 3.04, 3.01, 2.99, 2.95, 2.98, 2.93, 2.91, 2.91, 2.89, 2.9, 2.92, 2.93, 2.91, 2.94, 2.89, 2.92, 2.93, 3.01, 2.95, 2.97, 2.96, 2.96, 2.94, 2.94, 2.95, 2.97, 3.02, 3.0, 2.99, 3.02, 3.01, 3.03, 2.95, 2.95, 3.0, 2.95, 2.94, 3.0, 2.96, 2.95, 2.97, 2.98, 2.99, 3.0, 2.98, 3.01, 2.96, 2.96, 2.97, 2.98, 2.98, 2.95, 2.95, 2.95, 2.95, 2.95, 2.99, 2.95, 2.99, 2.98, 2.99, 3.0, 3.02, 3.05, 3.03, 3.01, 3.05, 3.06, 2.99, 3.03, 3.01, 2.99, 3.02, 3.0, 3.02, 3.01, 3.04, 3.02, 3.02, 3.03, 3.05, 3.03, 3.05, 3.01, 3.02, 3.0, 2.99, 2.95, 3.03, 2.99, 3.01, 2.99, 3.03, 3.01, 3.01, 3.02, 3.06, 3.09, 3.08, 3.07, 3.01, 3.09, 3.0, 3.12, 3.08, 3.02, 3.02, 3.11, 3.04, 3.04, 3.15, 3.05, 3.14, 3.06, 3.02, 3.13, 3.05, 3.2, 3.08, 3.1, 3.17, 3.16, 3.07, 3.16, 3.11, 3.09, 3.05, 3.24, 3.02, 3.07, 3.13, 3.01, 3.19, 3.29, 3.22, 3.22, 3.17, 3.16, 3.06, 3.15, 3.03, 3.15, 3.09, 3.05, 3.13, 3.03, 3.05, 3.06, 2.93, 2.94, 3.41, 2.94, 2.75, 3.01, 3.31, 3.28, 2.55, 3.16, 3.15, 2.83, 3.07, 3.04, 2.82, 3.32, 2.71, 2.23, 0.8, 3.53, 2.81, 2.65, 3.23, 3.03, null, null, -14.79, -19.27, -20.1, -20.23, -19.9, -19.92, -19.28, -18.25, -18.42, -18.81, -19.17, -18.4, -16.65, -16.87, -18.85, -19.69, -19.46, -19.01, -19.39, -17.72, -17.32, -19.62, -19.25, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null], "db": [-33.7, -29.3, -30.0, -33.2, -33.9, -34.4, -38.5, -37.2, -39.9, -37.3, -22.1, -13.9, -12.8, -11.8, -10.9, -10.1, -10.5, -10.4, -10.4, -9.6, -8.8, -8.7, -9.1, -9.1, -8.6, -8.3, -8.8, -9.8, -8.8, -8.6, -9.1, -9.1, -8.7, -8.2, -8.2, -8.4, -9.1, -8.3, -7.8, -8.2, -8.9, -8.2, -7.8, -8.1, -8.3, -8.5, -8.0, -7.9, -8.5, -9.3, -8.4, -8.1, -8.7, -9.2, -8.5, -8.4, -8.3, -8.5, -8.9, -8.2, -7.8, -8.3, -8.9, -8.0, -7.7, -8.2, -8.8, -8.6, -8.2, -8.2, -8.9, -9.5, -8.7, -8.6, -9.2, -9.8, -8.8, -8.4, -9.2, -9.7, -8.8, -8.7, -9.3, -9.9, -9.0, -8.9, -9.4, -9.8, -9.4, -9.0, -9.0, -9.5, -9.5, -8.7, -8.7, -9.3, -9.7, -8.6, -8.3, -9.1, -9.3, -8.3, -7.8, -8.2, -8.7, -7.5, -6.9, -7.6, -7.9, -7.0, -6.7, -7.1, -7.8, -6.8, -6.6, -7.4, -8.0, -7.1, -6.9, -7.7, -8.2, -7.3, -6.9, -7.6, -8.0, -7.0, -7.0, -7.6, -8.0, -6.9, -7.0, -7.6, -8.0, -7.0, -6.9, -7.7, -7.8, -6.8, -6.8, -7.4, -7.6, -6.7, -7.0, -7.8, -8.1, -7.7, -8.4, -10.1, -11.4, -14.5, -18.2, -17.8, -16.8, -17.1, -19.5, -23.1, -27.9, -30.5, -30.6, -33.0, -32.3, -23.7, -13.1, -12.2, -11.7, -10.7, -11.4, -9.4, -9.4, -9.3, -9.1, -10.6, -9.7, -10.9, -9.7, -10.5, -9.4, -9.5, -11.0, -9.6, -10.9, -9.9, -10.5, -10.4, -9.5, -10.9, -10.4, -10.6, -10.1, -9.4, -11.0, -10.2, -10.6, -10.0, -9.7, -10.9, -9.8, -10.8, -10.3, -10.4, -10.5, -9.9, -11.1, -10.5, -10.9, -10.3, -10.1, -11.3, -10.3, -11.2, -10.5, -11.0, -10.4, -9.8, -11.1, -10.2, -11.5, -10.6, -11.1, -10.8, -10.5, -11.3, -10.2, -11.2, -10.9, -11.2, -10.7, -10.7, -11.1, -10.7, -11.5, -11.1, -11.9, -11.9, -12.2, -11.9, -11.7, -11.8, -10.9, -11.3, -10.8, -11.2, -11.3, -11.2, -11.4, -10.9, -11.4, -10.8, -11.2, -11.3, -11.3, -11.4, -11.0, -11.4, -10.8, -11.4, -10.9, -11.2, -11.4, -11.4, -11.2, -10.6, -11.3, -10.6, -11.1, -10.9, -11.1, -11.3, -11.1, -11.1, -10.8, -11.6, -11.1, -11.4, -11.5, -11.8, -11.9, -11.2, -11.6, -11.0, -11.8, -11.2, -11.6, -11.7, -11.8, -11.8, -11.4, -12.0, -11.6, -12.5, -12.3, -13.1, -13.3, -14.5, -15.1, -16.5, -18.5, -21.2, -24.6, -29.1, -34.0, -37.2, -37.3, -37.6, -28.1, -24.7, -24.4, -33.3, -31.6, -31.3, -32.6, -35.3, -34.8, -33.7, -34.1, -36.5, -34.5, -33.5, -32.0, -31.3, -28.2, -26.6, -26.1, -23.9, -23.7, -21.8, -20.2, -18.0, -18.1, -16.5, -15.6, -16.0, -14.0, -14.0, -14.6, -12.5, -14.4, -12.5, -12.6, -13.7, -11.5, -12.3, -12.5, -10.8, -12.6, -10.4, -11.4, -12.3, -10.1, -12.2, -10.7, -10.9, -12.2, -10.1, -11.3, -10.9, -10.3, -11.6, -10.1, -10.7, -11.2, -9.6, -11.2, -10.1, -10.6, -11.4, -9.2, -10.9, -9.9, -10.0, -11.0, -9.2, -10.5, -10.0, -9.5, -10.4, -9.4, -10.2, -10.3, -9.7, -11.2, -10.4, -11.0, -11.1, -10.3, -12.1, -11.1, -11.6, -11.9, -10.2, -12.1, -10.7, -11.2, -11.8, -9.9, -12.2, -10.4, -11.0, -11.9, -10.3, -11.9, -10.8, -11.2, -12.2, -11.0, -11.7, -11.6, -10.8, -12.4, -10.9, -11.7, -12.1, -10.2, -12.1, -10.5, -11.4, -12.0, -10.1, -11.9, -10.6, -11.7, -12.1, -10.2, -12.1, -10.7, -11.1, -11.8, -10.3, -11.3, -10.9, -10.4, -11.7, -10.6, -11.1, -11.4, -9.9, -11.7, -10.7, -11.4, -11.9, -10.4, -12.4, -11.0, -11.5, -11.9, -10.5, -12.6, -11.0, -11.8, -11.8, -11.3, -13.0, -11.4, -12.4, -12.5, -11.2, -12.8, -11.2, -12.1, -12.9, -11.0, -13.2, -11.6, -12.3, -13.2, -10.7, -12.6, -11.5, -11.3, -12.5, -10.6, -11.9, -12.3, -10.7, -13.2, -12.3, -14.0, -15.5, -14.5, -16.2, -17.1, -16.7, -16.9, -17.1, -18.9, -18.3, -18.7, -17.6, -14.6, -13.2, -10.1, -11.8, -10.8, -11.2, -11.7, -11.5, -11.0, -11.0, -10.7, -10.2, -10.7, -10.7, -10.0, -10.8, -11.0, -10.3, -11.4, -11.8, -10.5, -11.6, -12.6, -11.2, -11.8, -12.7, -11.1, -12.0, -12.7, -11.6, -13.0, -13.4, -12.2, -13.6, -13.9, -13.1, -14.0, -14.7, -14.1, -15.9, -15.9, -16.7, -22.6, -28.9, -27.0, -29.4, -31.1, -32.5, -29.9, -33.5, -39.3, -35.1, -31.5, -29.8, -30.6, -32.6, -32.8, -32.1, -35.5, -35.6, -35.8, -35.3, -37.0, -37.6, -37.2, -37.2, -39.4, -40.8, -43.6, -42.3, -41.6, -40.4, -42.9, -42.2, -40.6, -38.1, -41.8, -43.2, -42.9, -44.1, -45.8, -47.4, -45.3, -42.4, -43.2, -42.2, -39.7, -47.3, -45.2, -48.8, -47.5, -54.1, -47.6, -52.5, -50.7, -50.4, -46.1, -45.6, -50.3, -46.8, -44.2, -48.6, -46.0, -45.8, -46.1, -53.3, -53.4, -53.8, -50.7, -50.5, -47.5, -46.6, -39.8, -40.7, -41.2, -40.5, -44.5, -46.7, -47.4, -49.8, -44.5, -52.7, -47.7, -52.4, -58.7, -62.4, -54.0, -53.7, -52.2, -49.6, -50.5, -56.8, -54.8, -54.2, -49.5, -52.4, -47.8, -48.8, -43.2, -48.8, -46.7, -46.7, -47.2, -47.6, -46.6, -46.8, -45.6, -43.8, -41.6, -37.3, -33.9, -18.0, -12.7, -10.9, -11.3, -11.2, -12.7, -13.0, -12.2, -12.4, -12.4, -13.3, -13.3, -12.8, -11.9, -11.7, -13.7, -13.7, -13.8, -12.1, -12.7, -12.7, -13.8, -13.5, -13.5, -11.7, -12.7, -12.6, -13.3, -13.4, -13.2, -11.6, -12.7, -13.4, -14.0, -13.8, -12.8, -12.6, -12.7, -14.1, -14.1, -14.0, -12.2, -13.8, -13.9, -14.6, -14.7, -13.8, -15.0, -15.5, -17.5, -19.5, -21.7, -18.9, -18.7, -19.0, -17.4, -16.9, -17.5, -16.8, -16.7, -18.0, -17.6, -17.9, -19.2, -18.2, -18.5, -18.8, -17.7, -18.4, -17.6, -16.6, -17.2, -16.8, -16.8, -17.1, -16.1, -17.0, -16.9, -16.6, -17.8, -16.8, -17.5, -18.0, -17.2, -18.0, -18.8, -17.4, -18.5, -17.7, -18.4, -18.8, -17.1, -18.3, -18.4, -17.9, -18.8, -18.2, -18.0, -19.0, -18.1, -18.8, -19.2, -18.1, -19.1, -18.5, -18.7, -19.7, -18.2, -19.0, -18.9, -18.7, -19.3, -18.3, -18.3, -18.4, -17.7, -18.5, -17.5, -17.4, -17.9, -16.7, -17.6, -16.2, -16.8, -16.5, -15.9, -16.3, -15.3, -16.2, -15.1, -15.9, -14.9, -16.6, -16.3, -18.0, -19.1, -21.4, -25.4, -24.1, -19.7, -16.1, -14.5, -14.4, -14.9, -15.9, -9.1, -7.4, -9.8, -8.8, -9.4, -10.3, -10.2, -10.9, -10.3, -10.7, -11.8, -10.1, -10.9, -11.1, -10.4, -11.9, -10.7, -11.1, -11.0, -10.3, -11.2, -10.6, -10.6, -10.4, -9.4, -10.7, -10.0, -10.2, -9.7, -9.5, -10.9, -9.8, -10.5, -10.2, -9.8, -11.1, -10.1, -10.7, -10.3, -9.4, -11.1, -10.0, -10.9, -10.2, -9.3, -11.1, -9.7, -10.6, -9.9, -9.2, -11.0, -9.6, -10.6, -10.1, -9.7, -11.1, -9.9, -10.8, -10.1, -10.0, -10.2, -9.3, -10.5, -9.6, -9.8, -9.4, -9.0, -10.4, -9.3, -9.9, -9.2, -9.1, -10.6, -9.4, -10.4, -9.7, -9.7, -10.7, -10.1, -11.2, -10.6, -11.3, -10.4, -10.5, -11.9, -11.3, -12.0, -11.1, -11.1, -11.7, -11.4, -11.9, -11.5, -11.3, -12.2, -11.4, -12.2, -11.4, -10.6, -11.6, -10.7, -11.8, -11.1, -10.4, -11.8, -10.9, -12.0, -11.2, -10.6, -11.7, -11.5, -12.0, -12.1, -12.3, -13.0, -15.0, -17.2, -20.3, -24.3, -28.1, -31.4, -31.0, -29.3, -32.5, -31.0, -32.2, -30.7, -28.3, -28.5, -21.4, -20.5, -20.1, -26.2, -23.4, -22.0, -24.7, -24.2, -23.4, -22.1, -25.3, -23.2, -24.2, -21.9, -20.6, -20.0, -22.3, -19.1, -22.7, -22.9, -21.8, -20.1, -22.0, -21.0, -22.1, -22.6, -21.8, -27.0, -26.2, -24.9, -27.1, -31.4, -33.0, -35.0, -35.2, -24.9, -15.9, -10.3, -11.6, -10.7, -10.7, -11.6, -11.5, -10.6, -10.9, -10.7, -10.1, -10.0, -10.7, -10.3, -10.9, -10.6, -10.6, -11.7, -10.8, -11.8, -12.6, -11.2, -11.9, -12.0, -10.9, -11.7, -11.6, -10.6, -11.4, -11.5, -10.7, -11.4, -11.3, -10.9, -11.8, -11.7, -11.1, -11.8, -11.6, -11.3, -11.9, -11.5, -11.6, -12.3, -11.7, -11.8, -12.5, -12.2, -12.5, -12.8, -12.7, -12.9, -13.5, -13.3, -13.1, -13.6, -13.8, -13.5, -14.0, -14.0, -13.6, -14.4, -14.2, -13.9, -14.8, -14.6, -14.5, -15.3, -15.1, -15.2, -15.9, -15.3, -16.4, -16.9, -16.8, -18.3, -18.3, -19.6, -20.8, -20.5, -22.9, -23.1, -25.8, -28.6, -29.3, -31.3, -34.4, -36.0, -38.7, -38.8, -38.4, -37.2, -37.9, -38.4, -38.2, -38.2, -42.2, -39.4, -41.0, -41.5, -41.6, -42.4, -40.8, -42.3, -42.0, -38.1, -39.1, -37.0, -40.1, -38.2, -39.7, -42.0, -40.2, -36.8, -37.3, -37.2, -38.4, -41.0, -41.3, -40.9, -37.3, -39.7, -39.3, -36.3, -36.0, -36.4, -35.7, -41.5, -40.7, -38.4, -38.7, -35.9, -39.5, -34.3, -32.4, -33.1, -33.3, -33.7, -36.4, -36.9, -36.5, -38.6, -37.4, -36.5, -39.9, -41.9, -38.8, -38.4, -25.4, -16.7, -15.4, -14.0, -14.6, -13.9, -14.6, -14.3, -13.5, -13.4, -13.3, -13.6, -13.3, -13.6, -14.0, -14.2, -14.8, -14.9, -15.6, -15.4, -14.9, -14.9, -14.3, -14.5, -15.3, -15.3, -15.4, -16.3, -16.4, -16.1, -15.8, -16.9, -16.8, -16.8, -16.8, -16.5, -16.8, -16.5, -16.7, -16.9, -17.0, -16.7, -15.6, -15.6, -15.5, -15.4, -14.4, -13.7, -14.7, -14.4, -14.5, -14.2, -14.7, -14.8, -14.5, -14.0, -13.7, -14.6, -14.0, -14.5, -14.9, -15.1, -14.6, -15.6, -16.0, -16.1, -16.6, -16.3, -16.9, -16.5, -16.7, -17.2, -17.6, -16.7, -17.7, -18.0, -17.8, -18.3, -18.7, -18.2, -18.6, -18.1, -18.5, -18.3, -17.8, -17.8, -17.4, -17.3, -17.6, -17.7, -17.7, -18.2, -18.6, -18.7, -18.5, -18.8, -19.5, -18.4, -18.8, -18.3, -18.6, -19.1, -19.1, -19.3, -19.5, -19.3, -19.6, -19.6, -19.5, -19.6, -19.5, -19.2, -20.2, -20.3, -19.8, -20.0, -20.1, -20.6, -21.0, -20.8, -21.6, -23.4, -24.2, -27.4, -32.7, -38.9, -37.8, -35.4, -33.5, -34.1, -34.4, -32.7, -38.0, -38.5, -38.8, -38.7, -40.4, -38.9, -36.1, -39.1, -36.2, -36.6, -41.1, -43.2, -43.0, -42.5, -43.8, -40.8, -43.5, -40.7, -42.3, -41.2, -41.8, -42.6, -44.4, -42.1, -41.9, -40.7, -37.3, -34.7, -40.1, -36.7, -37.4, -22.2, -16.5, -20.8, -16.8, -18.2, -16.7, -20.2, -18.8, -18.2, -16.9, -17.3, -16.5, -16.8, -17.6, -19.1, -16.9, -16.9, -16.6, -16.5, -16.5, -15.6, -16.8, -17.1, -18.2, -17.0, -17.5, -17.3, -18.3, -17.8, -18.6, -18.4, -19.9, -20.9, -20.9, -20.5, -20.8, -21.3, -21.6, -21.2, -20.6, -22.0, -22.0, -23.1, -23.1, -23.9, -27.2, -29.1, -32.5, -33.2, -35.6, -36.8, -36.6, -35.8, -36.6, -43.2, -39.1, -42.1, -47.2, -40.3, -40.4, -41.0, -50.9, -52.0, -56.0, -53.5, -49.5, -48.1, -34.5, -37.4, -39.0, -38.4, -36.3, -35.6, -41.2, -36.2, -35.7, -34.8, -41.1, -43.5, -40.3, -39.5, -43.0, -45.6, -42.8, -48.4, -54.2, -49.4, -50.6, -46.5, -42.3, -43.2, -43.2, -43.1, -41.5, -45.0, -45.0, -40.5, -39.5, -41.8, -41.4, -42.7, -46.9, -45.4, -43.9, -42.5, -42.4, -40.6, -43.7, -44.4, -42.6, -45.3, -46.3, -44.7, -40.5, -41.2, -45.4, -43.2, -40.2, -45.2, -45.1, -45.9, -45.7, -41.5, -45.1, -41.6, -43.2, -44.5, -46.3, -49.4, -48.9, -47.3, -45.0, -47.5, -48.1, -50.8, -45.5, -49.8, -48.2, -47.5, -52.3, -49.4, -52.8, -52.3, -54.9, -56.4, -50.6, -53.6, -55.4, -50.7, -47.6, -51.1, -51.0, -52.3, -50.9, -52.7, -55.5, -53.1, -57.1, -56.6, -53.4, -50.1, -50.4, -50.4, -52.0, -49.8, -48.8, -45.6, -44.4, -42.6, -42.3, -41.8, -40.7, -42.1, -41.1, -42.3, -37.4, -27.1, -19.0, -17.9, -15.4, -14.7, -12.0, -11.4, -10.6, -9.2, -9.4, -8.4, -8.7, -7.7, -8.2, -8.4, -7.4, -8.5, -8.2, -8.4, -8.8, -8.1, -8.6, -9.0, -8.1, -9.1, -9.4, -9.1, -10.4, -9.4, -9.4, -10.4, -9.5, -10.1, -10.6, -9.4, -9.9, -10.8, -10.5, -10.8, -10.6, -9.8, -10.5, -10.7, -10.0, -11.1, -10.1, -10.2, -10.3, -9.8, -10.1, -9.7, -9.0, -9.8, -9.1, -8.7, -9.7, -8.5, -8.5, -8.9, -8.1, -8.8, -9.5, -9.0, -9.7, -10.4, -9.4, -9.5, -9.5, -8.8, -9.9, -9.0, -9.2, -10.3, -9.3, -10.0, -9.8, -9.6, -9.5, -9.7, -8.7, -9.4, -9.7, -8.8, -9.1, -9.5, -8.4, -9.1, -9.1, -8.3, -9.5, -9.6, -8.9, -10.5, -10.0, -9.4, -10.4, -10.1, -10.5, -11.4, -11.0, -10.1, -11.5, -10.8, -11.1, -11.0, -9.9, -10.5, -10.2, -9.7, -10.0, -10.3, -9.0, -9.6, -9.7, -9.9, -10.4, -9.7, -10.4, -10.8, -10.0, -10.9, -10.9, -10.0, -11.0, -10.8, -9.7, -11.1, -10.3, -11.0, -11.2, -10.4, -10.5, -10.9, -10.4, -10.9, -11.9, -10.4, -10.8, -11.4, -11.3, -12.0, -11.1, -11.1, -11.7, -11.1, -11.7, -11.7, -11.6, -12.7, -12.0, -12.2, -12.5, -11.3, -12.1, -11.6, -10.7, -11.7, -11.6, -11.4, -11.4, -10.4, -12.1, -11.8, -10.1, -11.3, -11.3, -10.6, -11.3, -10.4, -10.9, -12.2, -10.6, -10.4, -11.1, -10.4, -11.1, -11.0, -10.5, -11.8, -10.6, -11.1, -11.8, -11.1, -11.4, -12.0, -11.2, -11.1, -11.6, -10.7, -11.2, -11.1, -11.1, -12.3, -10.8, -11.6, -12.6, -11.5, -11.3, -12.2, -10.9, -11.9, -12.2, -10.8, -11.5, -11.4, -10.5, -10.9, -11.6, -11.2, -11.5, -11.1, -11.9, -11.6, -11.1, -12.3, -12.1, -11.1, -12.7, -12.8, -11.4, -12.3, -13.4, -11.4, -11.8, -12.1, -11.3, -12.6, -11.7, -11.6, -12.6, -11.6, -11.3, -12.7, -11.4, -11.7, -11.5, -10.9, -11.9, -11.6, -10.7, -11.4, -11.4, -11.0, -12.1, -11.7, -11.0, -11.6, -11.9, -11.0, -12.3, -11.6, -11.8, -12.5, -11.4, -12.1, -13.3, -12.9, -13.1, -13.5, -12.7, -13.0, -13.2, -13.1, -13.3, -13.3, -11.7, -12.6, -12.2, -11.4, -12.4, -11.6, -12.1, -12.4, -11.7, -11.5, -12.1, -12.3, -12.8, -12.8, -12.6, -14.3, -13.8, -14.1, -14.0, -13.5, -15.0, -15.0, -14.7, -14.9, -15.2, -15.2, -15.3, -16.2, -16.1, -17.7, -19.1, -19.9, -23.3, -25.5, -27.7, -31.5, -34.8, -36.3, -35.8, -36.5, -37.8, -38.0, -39.4, -38.9, -39.9, -41.0, -42.2, -43.6, -44.1, -46.3, -47.0, -46.6, -42.9, -43.6, -36.4, -21.1, -13.3, -10.5, -10.9, -10.9, -10.7, -9.4, -9.4, -9.0, -9.4, -9.3, -9.7, -10.2, -10.6, -11.3, -12.5, -12.6, -12.0, -11.7, -10.5, -10.3, -9.9, -9.4, -9.1, -9.3, -8.1, -8.5, -8.6, -8.7, -8.7, -8.9, -8.0, -8.9, -9.2, -9.5, -9.8, -10.6, -11.0, -11.9, -12.7, -12.4, -12.7, -12.7, -12.7, -12.2, -12.1, -13.8, -14.0, -14.8, -15.4, -15.5, -17.0, -17.0, -17.4, -19.2, -20.6, -22.0, -21.9, -22.0, -23.5, -23.7, -24.4, -26.4, -27.0, -28.2, -29.2, -28.9, -29.5, -29.6, -30.5, -30.8, -32.1, -33.7, -35.1, -36.5, -38.5, -40.3, -41.0, -41.5, -41.7, -41.7, -43.1, -41.2, -38.3, -38.4, -33.9, -33.2, -31.1, -30.3, -30.5, -30.2, -29.8, -28.5, -29.8, -28.6, -30.7, -34.6, -30.8, -32.8, -31.6, -31.1, -29.9, -32.8, -29.8, -29.9, -29.3, -25.4, -25.0, -28.0, -27.0, -25.1, -22.2, -25.1, -20.7, -22.2, -19.6, -22.2, -22.4, -23.2, -23.0, -22.1, -23.6, -26.6, -22.4, -26.1, -23.2, -20.4, -24.0, -23.8, -19.6, -21.0, -18.2, -22.3, -24.6, -23.7, -25.8, -27.9, -29.2, -33.7, -34.7, -42.0, -43.7, -45.0, -43.3, -43.5, -45.0, -46.3, -49.6, -46.7, -48.0, -50.5, -52.1, -51.2, -52.6, -52.2, -55.4, -50.7, -31.2, -28.7, -26.1, -25.4, -25.4, -30.2, -26.6, -13.5, -10.8, -11.6, -11.0, -10.7, -11.9, -11.3, -10.5, -11.9, -10.7, -10.5, -11.6, -10.1, -11.1, -10.4, -9.9, -11.4, -10.0, -10.3, -10.3, -9.0, -10.4, -9.7, -9.8, -9.9, -8.6, -10.3, -9.5, -10.3, -9.3, -8.5, -10.2, -9.5, -9.9, -9.3, -8.6, -10.0, -9.3, -9.7, -9.3, -9.0, -9.5, -9.1, -9.8, -9.5, -9.8, -9.2, -9.0, -10.1, -9.6, -10.0, -9.5, -9.1, -10.2, -9.8, -10.2, -9.6, -9.6, -9.8, -9.5, -10.3, -9.9, -10.4, -9.7, -9.5, -10.6, -10.2, -10.9, -10.2, -10.1, -10.3, -10.1, -11.0, -10.3, -11.0, -10.6, -10.4, -10.7, -10.3, -11.4, -10.6, -11.1, -10.5, -10.2, -10.9, -10.1, -11.0, -10.6, -11.1, -10.4, -9.7, -10.8, -10.3, -11.1, -10.6, -10.9, -10.8, -10.3, -11.3, -10.9, -11.6, -11.2, -11.0, -11.2, -10.8, -11.9, -11.5, -12.0, -11.6, -11.5, -11.9, -11.6, -12.3, -12.1, -12.2, -12.2, -11.8, -12.7, -12.8, -12.8, -12.6, -12.7, -13.2, -12.8, -13.5, -13.3, -13.5, -13.5, -13.1, -14.0, -14.1, -14.7, -14.3, -14.3, -15.0, -15.4, -16.3, -17.2, -18.0, -18.3, -18.6, -18.9, -19.6, -20.0, -19.8, -19.6, -20.1, -20.4, -20.8, -20.4, -20.4, -20.7, -20.9, -20.9, -20.3, -20.1, -20.8, -20.9, -21.0, -21.2, -21.6, -22.5, -23.2, -23.5, -23.8, -24.7, -25.2, -26.1, -27.6, -28.1, -29.4, -30.8, -33.0, -34.4, -37.5, -39.1, -42.8, -45.1, -47.6, -50.9, -53.3, -52.5, -55.0, -51.2, -50.8, -52.9, -47.5, -49.8, -54.8, -48.4, -46.0, -50.7, -53.8, -54.3, -57.9, -56.8, -54.2, -56.5, -49.1, -50.1, -61.7, -50.0, -51.1, -51.5, -52.4, -47.6, -50.0, -49.1, -45.7, -50.2, -48.7, -50.8, -51.2, -47.7, -46.5, -51.9, -43.6, -42.9, -46.3, -45.4, -41.8, -47.1, -45.1, -48.6, -46.9, -48.2, -48.5, -48.2, -43.3, -42.1, -46.1, -43.7, -43.3, -44.8, -47.0, -45.7, -45.7, -47.5, -44.8, -42.5, -41.2, -40.7, -51.6, -43.6, -44.1, -49.7, -47.2, -55.0, -47.9, -44.6, -51.6, -49.8, -51.1, -48.3, -54.7, -46.0, -46.6, -45.3, -46.3, -48.3, -51.9, -52.7, -51.5, -58.2, -55.1, -53.5, -55.5, -56.5, -64.6, -62.5, -59.3, -52.0, -50.7, -53.3, -52.0, -48.4, -55.6, -58.4, -55.1, -57.2, -53.6, -52.4, -55.9, -47.0, -47.8, -51.0, -49.6, -49.6, -50.9, -48.0, -47.0, -49.4, -55.8, -47.4, -47.7, -51.8, -52.6, -53.5, -51.6, -37.1, -39.2, -37.6, -29.7, -29.6, -28.5, -27.8, -26.8, -26.5, -25.0, -24.7, -25.1, -26.2, -25.9, -23.8, -24.2, -23.1, -24.8, -23.5, -25.6, -24.7, -28.8, -32.0, -32.9, -32.3, -21.0, -16.1, -12.9, -13.0, -12.5, -10.8, -12.8, -12.9, -10.8, -11.3, -11.2, -9.7, -10.1, -10.7, -9.3, -10.2, -11.1, -10.1, -11.7, -12.8, -12.9, -14.8, -14.4, -14.5, -13.7, -11.1, -11.3, -11.2, -12.1, -11.9, -11.0, -11.6, -12.9, -11.7, -12.6, -12.3, -13.5, -13.4, -12.7, -13.1, -13.3, -13.5, -13.6, -13.2, -12.2, -12.1, -12.5, -10.3, -10.7, -11.3, -9.2, -9.9, -10.2, -8.8, -9.4, -9.7, -8.4, -9.5, -10.0, -9.0, -10.1, -10.7, -10.3, -10.9, -11.4, -11.1, -12.1, -12.7, -12.6, -13.1, -14.0, -13.8, -13.8, -14.4, -14.2, -14.1, -13.8, -14.0, -13.8, -13.6, -14.1, -13.3, -13.1, -13.7, -13.2, -13.0, -13.2, -13.2, -12.8, -12.5, -13.2, -12.5, -12.4, -13.2, -12.7, -12.7, -13.4, -13.1, -13.2, -13.2, -13.3, -13.3, -12.6, -13.0, -13.3, -12.4, -13.0, -13.4, -12.4, -13.4, -13.7, -13.0, -13.8, -14.1, -13.8, -14.6, -14.5, -14.2, -15.0, -14.7, -14.6, -15.4, -15.4, -15.2, -15.8, -15.4, -15.8, -16.4, -16.0, -16.2, -17.2, -16.9, -16.9, -17.7, -17.5, -17.3, -18.5, -18.1, -17.9, -19.3, -18.7, -18.6, -19.8, -20.2, -20.2, -21.1, -22.5, -22.9, -24.7, -28.6, -30.9, -34.0, -34.9, -34.1, -36.0, -34.1, -34.1, -34.5, -33.9, -32.5, -32.6, -33.4, -32.3, -35.0, -33.0, -37.9, -30.6, -34.7, -33.0, -33.5, -33.4, -32.9, -36.2, -35.9, -34.7, -31.7, -35.4, -38.8, -39.3, -39.3, -35.0, -38.4, -36.6, -35.8, -36.5, -35.1, -36.9, -35.9, -38.3, -37.4, -40.0, -38.0, -39.4, -39.0, -38.1, -34.6, -39.8, -36.7, -35.3, -39.3, -41.5, -39.6, -36.7, -40.1, -41.2, -42.7, -44.4, -45.4, -47.7, -47.2, -48.9, -51.3, -51.7, -51.4, -55.0, -58.2, -58.4, -53.1, -49.1, -51.4, -50.7, -51.4, -48.6, -34.3, -39.4, -36.8, -34.1, -39.0, -42.4, -39.6, -43.9, -43.9, -41.8, -43.9, -44.0, -45.6, -53.2, -50.0, -48.1, -45.9, -48.0, -44.9, -43.2, -45.9, -43.9, -53.1, -49.1, -59.4, -56.4, -47.8, -44.3, -49.6, -45.6, -54.9, -50.7, -63.9, -53.1, -62.0, -56.9, -48.8, -50.2, -52.5, -61.9, -52.8, -57.1, -49.8, -53.4, -53.7, -57.8, -53.1, -64.0, -61.1, -56.5, -61.5, -58.3, -60.0, -66.0, -57.3, -56.1, -64.4, -61.8, -56.9, -51.7, -48.4, -49.6, -52.9, -48.0, -50.7, -48.9, -50.6, -46.6, -44.9, -47.0, -43.2, -43.7, -40.2, -38.8, -36.7, -39.5, -40.7, -39.8, -34.9, -31.2, -25.6, -21.7, -19.5, -17.3, -16.6, -17.5, -17.5, -16.7, -15.9, -15.3, -15.8, -14.0, -13.6, -14.0, -13.2, -12.7, -12.2, -10.8, -11.3, -10.1, -10.3, -11.8, -10.6, -12.6, -10.6, -10.7, -10.8, -9.1, -10.6, -8.4, -9.4, -9.2, -9.1, -10.0, -9.0, -9.9, -9.9, -9.3, -10.0, -9.3, -9.5, -9.8, -8.5, -9.7, -8.8, -9.1, -9.5, -7.9, -9.8, -8.8, -9.0, -9.4, -8.1, -9.9, -8.7, -8.9, -9.6, -8.0, -10.0, -8.8, -9.0, -9.9, -8.6, -10.6, -9.5, -9.8, -10.8, -9.5, -11.9, -10.5, -11.2, -11.6, -11.1, -13.2, -11.3, -12.6, -12.3, -12.1, -13.5, -11.8, -14.2, -13.1, -13.0, -13.8, -12.5, -14.6, -12.6, -13.3, -13.2, -12.7, -14.2, -12.2, -14.1, -13.1, -12.8, -13.7, -12.6, -14.7, -13.1, -13.5, -13.8, -13.4, -14.7, -12.8, -14.2, -13.6, -13.5, -14.5, -13.0, -14.7, -13.7, -13.5, -14.0, -13.6, -15.2, -13.6, -13.9, -13.9, -13.9, -14.9, -13.5, -14.8, -14.2, -14.3, -15.0, -14.1, -15.5, -14.7, -14.8, -15.5, -14.8, -15.7, -14.8, -15.2, -15.3, -15.1, -15.8, -14.9, -15.3, -15.6, -15.3, -16.0, -15.2, -15.4, -15.6, -15.3, -16.1, -15.3, -15.5, -15.3, -15.7, -16.3, -15.6, -16.1, -15.4, -15.8, -16.6, -15.3, -15.9, -15.3, -15.8, -16.4, -15.3, -16.1, -15.5, -15.6, -16.0, -14.9, -16.2, -15.2, -15.3, -15.9, -15.3, -17.0, -15.8, -16.0, -16.9, -17.1, -19.0, -22.2, -21.0, -21.4, -23.4, -28.2, -31.1, -28.3, -26.9, -25.2, -17.5, -12.7, -12.4, -14.5, -12.5, -12.6, -14.0, -11.6, -12.3, -13.0, -11.5, -13.2, -14.2, -13.3, -14.2, -15.5, -14.1, -14.4, -15.6, -14.1, -14.8, -15.2, -13.8, -15.0, -15.4, -14.1, -15.2, -16.0, -15.1, -16.0, -16.4, -15.0, -16.2, -16.7, -15.5, -16.1, -17.1, -15.8, -16.8, -17.2, -16.2, -17.4, -18.2, -16.8, -18.0, -18.9, -17.8, -19.0, -19.7, -18.8, -20.3, -20.6, -20.3, -22.0, -22.9, -21.9, -24.3, -23.5, -23.2, -24.1, -22.4, -22.7, -22.7, -21.9, -22.5, -21.3, -21.6, -22.3, -21.2, -22.0, -22.2, -21.1, -21.9, -22.1, -21.7, -22.7, -22.2, -21.7, -23.5, -23.1, -23.0, -24.8, -23.8, -24.2, -25.5, -24.2, -23.8, -25.3, -24.8, -23.9, -25.5, -24.7, -24.8, -25.6, -24.5, -25.9, -25.2, -25.4, -25.8, -24.3, -24.3, -24.9, -24.1, -24.4, -24.8, -23.9, -24.4, -23.1, -23.1, -24.2, -22.6, -22.3, -23.8, -22.9, -23.2, -23.5, -23.1, -24.0, -24.2, -24.1, -24.2, -23.9, -24.0, -24.8, -23.7, -24.3, -25.5, -24.1, -25.6, -24.8, -25.3, -26.6, -25.9, -26.0, -29.1, -25.7, -27.1, -26.7, -25.9, -29.0, -25.8, -25.6, -26.1, -26.2, -25.7, -26.3, -26.9, -28.6, -28.7, -28.1, -27.6, -29.0, -24.8, -21.4, -19.8, -16.6, -16.2, -16.1, -15.0, -12.9, -13.3, -14.2, -14.1, -13.0, -12.8, -13.5, -13.7, -13.5, -12.5, -12.1, -12.4, -13.1, -13.0, -12.9, -12.1, -12.4, -13.6, -13.3, -12.9, -11.8, -11.4, -12.9, -12.7, -12.7, -11.1, -10.8, -12.2, -11.6, -11.8, -10.8, -10.2, -11.9, -11.9, -12.0, -10.8, -10.4, -12.0, -11.9, -12.2, -10.8, -10.6, -12.4, -12.1, -12.2, -11.0, -10.5, -12.2, -12.1, -12.2, -10.9, -10.9, -12.5, -12.4, -12.4, -11.4, -11.2, -12.5, -12.6, -12.6, -12.5, -11.9, -12.0, -13.3, -13.6, -13.6, -12.2, -12.1, -13.8, -13.8, -13.7, -13.4, -12.6, -12.4, -13.7, -13.1, -13.1, -12.0, -11.8, -13.1, -12.8, -13.0, -12.2, -11.8, -12.0, -12.7, -12.8, -12.8, -11.5, -11.4, -12.7, -12.7, -12.6, -11.6, -11.9, -12.9, -13.0, -12.7, -12.9, -12.2, -12.3, -13.2, -13.0, -13.2, -11.8, -12.0, -13.0, -13.0, -13.1, -13.0, -12.5, -12.9, -14.4, -14.2, -14.4, -14.3, -14.2, -14.0, -15.2, -15.1, -15.1, -13.9, -14.0, -15.2, -15.0, -15.0, -14.4, -13.8, -13.9, -14.9, -14.6, -14.6, -13.2, -13.3, -14.9, -14.7, -15.0, -14.1, -14.5, -14.9, -16.2, -16.3, -16.5, -15.5, -16.1, -15.2, -16.3, -16.0, -15.8, -15.8, -16.0, -15.9, -16.1, -16.0, -15.4, -15.4, -15.0, -15.5, -15.9, -15.9, -16.5, -16.9, -16.4, -16.6, -16.5, -15.9, -15.5, -15.3, -15.2, -15.3, -15.6, -16.2, -16.8, -17.0, -17.4, -17.5, -18.0, -18.5, -18.1, -18.5, -18.9, -19.6, -20.0, -20.7, -21.9, -21.4, -22.0, -21.5, -22.2, -22.5, -23.1, -22.8, -25.6, -27.6, -35.1, -35.3, -36.5, -34.3, -35.5, -35.6, -36.0, -40.9, -43.1, -44.2, -46.3, -42.5, -42.1, -42.0, -43.4, -41.4, -43.7, -42.5, -43.5, -45.5, -42.3, -44.1, -44.6, -39.8, -42.6, -42.7, -41.5, -42.5, -42.6, -43.3, -42.5, -40.4, -40.9, -42.1, -42.5, -41.7, -40.8, -40.9, -42.3, -40.8, -45.8, -42.2, -40.2, -42.1, -39.8, -39.0, -42.5, -43.5, -40.8, -43.0, -45.6, -46.4, -43.9, -45.0, -43.0, -42.5, -41.3, -41.9, -41.3, -44.6, -48.2, -47.6, -46.9, -46.5, -44.7, -45.3, -44.8, -47.1, -47.6, -53.1, -53.2, -52.1, -53.1, -55.5, -57.5, -61.2, -60.0, -64.2, -62.4, -58.7, -55.3, -61.7, -57.7, -57.3, -57.5, -50.1, -49.2, -45.1, -47.0, -48.5, -47.5, -44.3, -41.9, -38.9, -37.2, -34.1, -28.6, -25.7, -27.6, -27.2, -27.5, -29.3, -26.4, -27.8, -29.4, -29.4, -30.7, -32.5, -31.8, -33.3, -32.3, -31.0, -31.3, -28.7, -25.0, -22.8, -19.1, -17.6, -15.7, -11.0, -8.4, -8.1, -6.7, -6.1, -5.3, -6.0, -6.2, -7.1, -6.6, -7.2, -7.8, -8.4, -8.0, -9.0, -8.3, -8.3, -8.7, -9.2, -9.1, -10.0, -9.1, -9.0, -9.0, -9.6, -9.6, -10.4, -9.4, -9.3, -9.2, -9.3, -9.7, -8.6, -8.5, -8.2, -8.5, -8.6, -8.4, -7.9, -7.8, -8.2, -8.2, -8.6, -7.9, -7.6, -8.3, -8.2, -8.6, -7.7, -7.8, -8.7, -8.2, -8.4, -7.5, -7.6, -8.4, -8.2, -8.3, -7.8, -7.7, -8.4, -8.5, -8.1, -7.8, -8.0, -8.4, -9.1, -8.0, -7.9, -8.4, -8.4, -9.4, -8.2, -7.9, -8.7, -8.6, -9.1, -8.3, -8.4, -9.2, -9.5, -8.7, -8.6, -9.0, -9.2, -9.8, -8.7, -8.6, -9.5, -9.4, -9.6, -8.8, -9.1, -10.2, -10.1, -9.7, -9.3, -10.1, -10.5, -11.2, -10.0, -10.3, -11.4, -11.1, -11.8, -11.1, -11.4, -12.7, -12.7, -14.0, -14.0, -14.1, -15.1, -16.1, -17.3, -19.5, -21.3, -25.1, -27.0, -27.4, -27.8, -28.1, -30.1, -29.9, -29.5, -29.5, -29.7, -29.1, -27.8, -29.9, -26.5, -28.4, -28.7, -30.2, -28.1, -28.5, -28.3, -28.1, -27.8, -28.4, -25.8, -25.8, -27.8, -23.7, -25.6, -27.0, -25.7, -24.6, -24.8, -24.3, -24.9, -24.4, -23.2, -27.0, -23.5, -24.4, -26.1, -27.8, -29.5, -34.7, -35.2, -34.4, -23.2, -13.5, -10.7, -10.2, -10.7, -9.8, -9.5, -9.1, -8.8, -10.1, -8.9, -9.9, -9.1, -9.0, -10.1, -8.8, -10.1, -9.5, -9.9, -9.8, -9.1, -10.8, -9.7, -10.2, -9.8, -9.3, -10.6, -9.6, -10.3, -9.9, -9.8, -10.5, -9.8, -10.8, -10.5, -10.3, -10.7, -10.2, -11.5, -11.3, -11.3, -11.9, -12.2, -13.7, -13.8, -13.2, -13.1, -13.0, -13.1, -12.9, -13.9, -14.4, -15.2, -15.6, -16.6, -17.7, -18.1, -19.2, -21.0, -22.9, -25.5, -27.5, -30.5, -34.2, -36.9, -37.5, -36.8, -38.1, -40.4, -39.6, -42.8, -41.0, -42.1, -41.0, -43.9, -45.4, -49.3, -43.5, -44.6, -43.8, -47.9, -45.2, -49.4, -41.8, -41.3, -41.2, -42.8, -40.2, -45.5, -50.4, -51.4, -47.1, -47.8, -48.7, -54.7, -52.6, -46.5, -47.4, -48.6, -48.7, -45.3, -47.7, -49.2, -47.5, -50.7, -54.3, -49.5, -54.0, -52.5, -54.1, -52.6, -53.3, -49.7, -50.9, -43.3, -46.4, -42.4, -44.1, -44.9, -47.0, -43.5, -41.3, -49.8, -49.0, -50.9, -48.7, -45.0, -47.2, -44.5, -43.1, -43.8, -45.1, -47.4, -50.5, -47.6, -45.4, -47.8, -47.4, -46.1, -42.4, -41.0, -44.3, -45.7, -42.7, -44.6, -41.3, -39.1, -41.3, -38.9, -36.9, -36.1, -34.8, -33.9, -32.6, -32.3, -32.2, -33.2, -33.2, -32.5, -32.5, -33.1, -33.2, -34.2, -32.4, -31.8, -32.4, -30.7, -33.1, -31.1, -33.4, -31.6, -30.1, -18.4, -14.2, -14.0, -13.5, -15.1, -13.8, -12.8, -14.6, -11.4, -11.6, -11.8, -10.5, -12.5, -11.0, -11.4, -12.6, -11.2, -11.0, -10.6, -10.6, -11.5, -10.5, -10.2, -10.5, -10.7, -11.3, -10.8, -11.2, -11.2, -11.7, -12.1, -11.5, -12.0, -11.6, -11.4, -11.7, -11.5, -11.7, -11.6, -11.3, -11.2, -11.3, -11.7, -11.3, -11.6, -11.4, -11.3, -11.4, -11.4, -11.9, -11.9, -11.6, -11.9, -12.2, -13.0, -12.5, -12.7, -12.7, -13.2, -13.5, -12.8, -13.0, -12.7, -13.2, -13.6, -12.9, -13.7, -13.3, -13.6, -14.3, -13.8, -14.6, -13.9, -14.0, -14.4, -13.5, -13.8, -13.2, -13.6, -14.0, -13.9, -14.3, -13.8, -14.3, -14.5, -14.5, -15.2, -14.7, -14.8, -14.8, -15.2, -15.6, -15.2, -15.5, -15.3, -15.5, -16.0, -15.1, -14.9, -14.8, -15.5, -15.9, -14.9, -15.2, -15.1, -15.5, -15.6, -15.5, -15.6, -15.6, -15.4, -15.6, -16.0, -17.4, -18.4, -21.1, -27.1, -29.0, -26.0, -25.9, -25.2, -25.3, -25.8, -26.4, -26.7, -27.7, -29.1, -29.2, -28.9, -29.0, -30.3, -31.7, -34.6, -36.4, -40.4, -38.6, -38.2, -37.0, -38.5, -38.5, -39.9, -39.5, -40.5, -42.5, -41.4, -41.7, -41.2, -42.4, -41.3, -41.7, -40.4, -39.7, -38.7, -37.0, -37.6, -37.6, -34.2, -33.3, -34.0, -32.6, -31.5, -32.6, -33.1, -34.5, -34.5, -33.7, -31.8, -27.8, -17.0, -10.3, -9.7, -10.6, -9.4, -9.4, -9.2, -8.6, -9.9, -9.0, -8.5, -10.2, -9.1, -10.1, -9.2, -8.5, -9.6, -8.6, -9.6, -8.4, -7.6, -8.7, -7.8, -8.6, -7.5, -7.3, -8.6, -7.7, -8.5, -7.3, -7.2, -8.3, -7.5, -8.2, -7.3, -7.3, -8.2, -7.2, -8.2, -7.3, -7.2, -8.0, -7.0, -8.2, -7.2, -7.0, -8.0, -7.5, -8.5, -7.4, -7.3, -8.1, -7.6, -8.6, -7.4, -7.2, -8.2, -7.5, -8.4, -7.2, -7.2, -8.3, -7.2, -8.2, -7.5, -7.3, -8.2, -7.3, -8.2, -7.8, -7.5, -8.5, -7.6, -8.5, -7.9, -7.4, -8.4, -8.0, -8.8, -8.1, -7.6, -8.6, -8.3, -8.9, -8.0, -7.6, -8.6, -8.3, -8.7, -8.1, -7.6, -8.8, -8.3, -8.9, -8.4, -8.1, -8.9, -8.5, -9.2, -8.7, -8.3, -9.2, -8.7, -9.5, -9.0, -8.5, -9.0, -8.8, -9.6, -8.7, -8.4, -9.1, -8.9, -9.5, -8.8, -8.7, -9.2, -9.1, -9.7, -9.0, -9.0, -9.5, -9.2, -9.9, -9.4, -9.6, -10.4, -11.8, -14.8, -18.2, -21.5, -26.2, -30.9, -33.3, -32.4, -33.6, -35.5, -36.2, -40.1, -36.8, -36.0, -40.9, -41.0, -44.3, -41.5, -42.0, -42.8, -41.6, -46.3, -45.3, -45.9, -44.7, -48.8, -44.9, -32.6, -28.8, -25.0, -20.7, -21.5, -20.8, -24.4, -25.9, -28.2, -28.1, -30.5, -31.2, -32.4, -33.9, -33.2, -33.7, -32.3, -33.7, -32.7, -32.4, -32.8, -33.9, -33.5, -33.9, -31.1, -31.9, -32.4, -35.3, -34.8, -34.5, -35.3, -36.3, -35.8, -30.0, -25.8, -23.3, -19.4, -18.4, -16.0, -12.6, -10.3, -10.0, -10.0, -10.7, -9.0, -8.3, -8.4, -8.9, -10.3, -8.7, -8.5, -8.8, -9.1, -9.6, -8.2, -8.4, -8.8, -9.5, -9.1, -8.4, -8.4, -8.8, -9.4, -8.8, -8.3, -8.1, -8.5, -9.4, -8.7, -8.4, -8.0, -8.5, -9.3, -8.5, -8.1, -8.1, -8.6, -9.6, -8.2, -7.9, -7.9, -8.4, -9.4, -8.2, -8.2, -8.4, -8.8, -9.3, -8.2, -8.0, -8.5, -8.8, -9.0, -8.4, -8.3, -8.7, -9.2, -9.0, -8.4, -8.4, -8.9, -9.7, -8.7, -8.6, -8.3, -8.9, -10.2, -8.9, -8.6, -8.8, -9.1, -9.7, -8.6, -8.7, -9.2, -9.9, -9.3, -8.6, -8.4, -8.9, -10.0, -8.2, -8.1, -8.5, -9.2, -9.4, -8.5, -8.4, -9.1, -10.2, -8.6, -8.5, -9.3, -10.2, -9.4, -9.1, -9.5, -10.2, -10.7, -10.0, -10.2, -10.9, -11.9, -10.6, -10.6, -11.3, -11.5, -11.5, -10.6, -10.3, -10.9, -11.4, -10.7, -10.6, -10.9, -11.7, -12.9, -11.7, -11.9, -12.8, -12.7, -13.5, -12.6, -12.7, -13.6, -14.0, -13.6, -13.5, -14.3, -14.8, -15.7, -15.1, -15.8, -16.9, -17.9, -17.0, -17.4, -18.4, -18.6, -18.6, -18.6, -19.2, -19.6, -20.9, -20.3, -20.5, -21.6, -21.7, -23.1, -22.3, -22.8, -23.8, -23.3, -23.6, -23.6, -23.4, -24.7, -23.8, -24.8, -24.9, -25.8, -26.8, -28.1, -28.8, -30.6, -31.8, -34.7, -35.1, -36.1, -38.8, -40.6, -43.3, -41.5, -41.9, -46.6, -49.4, -49.3, -51.7, -53.1, -48.4, -44.7, -44.3, -49.3, -43.6, -41.4, -43.6, -47.2, -46.7, -43.7, -44.4, -47.1, -50.8, -47.5, -53.7, -58.0, -54.8, -50.7, -49.8, -56.5, -52.6, -50.1, -50.6, -50.6, -49.2, -51.7, -47.4, -44.7, -46.4, -46.9, -54.4, -49.5, -50.0, -53.6, -45.9, -42.0, -40.1, -38.8, -41.4, -44.0, -43.4, -43.7, -43.8, -45.5, -44.2, -47.1, -48.7, -47.5, -47.7, -46.6, -45.6, -46.7, -42.1, -42.0, -42.9, -46.1, -45.5, -49.0, -49.7, -44.9, -45.9, -44.5, -42.0, -41.2, -42.6, -49.5, -49.0, -48.4, -48.7, -45.8, -46.8, -45.6, -39.3, -39.4, -42.4, -46.2, -44.0, -46.1, -44.9, -41.2, -43.9, -44.8, -44.0, -43.2, -39.0, -40.3, -43.9, -40.9, -42.5, -39.9, -41.3, -47.6, -44.3, -42.5, -43.8, -50.1, -52.1, -48.4, -47.3, -47.1, -48.8, -51.1, -59.7, -51.0, -48.6, -44.0, -44.2, -42.0, -45.8, -52.9, -47.9, -46.7, -46.5, -47.1, -46.3, -47.2, -49.8, -45.5, -45.2, -51.0, -50.5, -52.8, -50.7, -57.3, -54.6, -54.2, -51.0, -51.6, -65.5, -54.7, -53.0, -53.6, -57.1, -59.4, -54.7, -51.1, -49.4, -54.5, -51.6, -48.4, -31.7, -28.5, -26.7, -23.8, -24.5, -25.4, -25.3, -24.6, -27.3, -27.1, -27.3, -28.7, -29.6, -32.1, -30.2, -30.1, -30.0, -30.5, -31.1, -31.7, -32.4, -34.0, -35.4, -35.2, -36.2, -36.7, -35.3, -30.7, -27.3, -23.5, -19.5, -15.8, -14.0, -13.3, -13.0, -13.7, -12.5, -12.9, -12.8, -12.9, -13.5, -12.8, -14.5, -13.4, -13.2, -13.8, -12.9, -14.7, -13.2, -13.4, -13.8, -13.4, -14.9, -13.3, -13.9, -13.8, -13.6, -14.7, -12.6, -13.9, -13.4, -13.2, -14.3, -12.4, -14.5, -13.1, -12.9, -14.1, -12.7, -14.8, -13.1, -13.3, -13.7, -13.0, -14.8, -12.8, -13.9, -13.3, -13.1, -14.4, -12.2, -14.2, -13.1, -12.8, -13.9, -12.3, -14.6, -12.9, -13.0, -13.6, -13.5, -14.3, -12.7, -14.4, -13.2, -13.0, -13.0, -12.5, -14.0, -12.3, -13.2, -12.8, -12.5, -14.0, -12.0, -13.9, -13.2, -13.3, -14.4, -12.6, -15.0, -13.5, -13.7, -14.3, -13.3, -15.6, -13.8, -14.4, -14.6, -14.0, -15.9, -13.7, -14.9, -14.4, -14.2, -15.7, -13.2, -15.4, -14.8, -14.9, -15.2, -14.4, -16.4, -14.5, -15.3, -15.0, -14.6, -16.0, -13.8, -15.8, -14.9, -14.6, -15.4, -14.1, -16.5, -15.2, -15.4, -15.7, -15.2, -17.2, -15.2, -16.5, -15.9, -15.8, -16.8, -15.0, -16.9, -16.0, -16.1, -16.6, -15.6, -18.2, -16.5, -17.1, -17.0, -16.4, -18.1, -16.2, -18.5, -17.1, -16.8, -17.3, -16.6, -17.8, -16.7, -18.1, -17.3, -16.6, -17.7, -16.9, -17.9, -17.1, -18.0, -17.9, -17.6, -18.5, -18.0, -19.0, -19.1, -20.8, -22.1, -22.7, -24.6, -26.1, -27.6, -29.0, -30.9, -32.8, -34.1, -37.7, -41.9, -42.2, -43.4, -39.9, -39.6, -41.9, -42.8, -43.4, -41.9, -42.1, -43.7, -42.1, -43.7, -44.2, -47.1, -46.2, -46.5, -51.0, -49.9, -48.4, -54.0, -51.4, -54.2, -53.3, -49.5, -49.5, -50.0, -46.2, -45.7, -49.4, -51.1, -52.8, -55.6, -52.1, -45.5, -49.8, -52.6, -48.9, -51.5, -52.0, -51.1, -54.2, -45.7, -48.1, -49.6, -45.9, -45.7, -48.2, -46.9, -46.4, -46.4, -45.8, -44.5, -42.6, -43.9, -48.5, -47.1, -51.9, -50.6, -55.1, -45.0, -42.6, -51.3, -44.1, -47.9, -54.7, -55.3, -51.3, -46.8, -46.4, -51.6, -46.6, -44.4, -46.0, -54.7, -41.9, -39.6, -41.7, -49.7, -53.8, -48.0, -49.2, -51.3, -48.2, -54.4, -51.3, -52.2, -53.0, -54.2, -56.1, -51.4, -54.9, -50.8, -53.5, -52.9, -50.5, -57.7, -60.5, -57.6, -59.1, -51.5, -46.7, -47.5, -57.9, -49.7, -49.0, -48.3, -51.3, -50.5, -49.5, -48.4, -44.8, -43.8, -50.5, -48.2, -49.4, -49.6, -50.0, -47.9, -46.0, -47.8, -47.0, -60.8, -50.6, -53.5, -47.5, -50.8, -48.4, -50.2, -53.4, -53.6, -55.5, -61.7, -51.7, -48.3, -48.1, -53.9, -50.0, -47.0, -46.8, -39.1, -38.0, -35.5, -32.7, -29.9, -30.5, -29.1, -30.9, -29.2, -31.3, -28.0, -30.7, -29.5, -27.4, -31.0, -30.3, -30.4, -30.0, -31.6, -32.8, -31.8, -31.0, -31.1, -30.5, -32.6, -33.1, -29.3, -30.6, -33.0, -31.2, -32.6, -31.9, -27.1, -25.4, -23.5, -21.5, -19.2, -16.7, -15.9, -14.8, -13.0, -13.2, -11.4, -12.9, -11.4, -11.0, -10.2, -10.2, -10.7, -8.8, -10.0, -9.4, -9.4, -9.9, -9.0, -9.8, -8.7, -9.9, -9.5, -9.2, -10.3, -9.2, -10.3, -9.7, -9.8, -10.5, -10.0, -10.7, -9.9, -10.7, -11.0, -11.1, -11.7, -11.1, -12.3, -11.8, -12.4, -12.9, -11.9, -13.2, -12.2, -12.5, -13.0, -11.5, -12.5, -12.0, -12.4, -13.1, -11.7, -13.0, -12.4, -12.5, -12.8, -11.5, -13.0, -12.0, -12.4, -12.3, -12.3, -13.4, -12.0, -12.9, -12.5, -12.9, -13.5, -12.2, -13.1, -12.5, -13.0, -13.2, -11.8, -13.0, -12.6, -12.9, -13.2, -12.1, -13.3, -12.7, -12.7, -13.5, -12.2, -13.6, -12.6, -12.9, -13.3, -12.2, -13.6, -11.9, -12.7, -12.2, -12.2, -12.9, -11.1, -12.6, -12.0, -12.0, -12.9, -11.8, -13.0, -12.7, -12.8, -13.8, -12.9, -14.1, -12.9, -13.5, -13.6, -13.5, -13.9, -12.5, -14.2, -13.8, -14.3, -14.7, -13.4, -14.9, -14.4, -14.2, -15.1, -14.3, -15.5, -14.2, -14.5, -14.9, -14.6, -15.6, -14.8, -16.3, -15.7, -16.9, -16.4, -16.4, -17.5, -16.7, -17.0, -16.7, -17.2, -17.4, -16.5, -17.4, -16.7, -17.1, -17.1, -16.4, -17.9, -17.0, -17.7, -16.7, -18.2, -18.2, -17.4, -18.4, -17.6, -19.3, -17.5, -19.2, -19.9, -19.4, -19.5, -18.8, -19.2, -19.8, -20.3, -21.7, -21.2, -22.5, -22.1, -23.5, -25.3, -24.8, -26.5, -25.7, -28.4, -28.1, -30.2, -30.5, -29.8, -31.4, -31.5, -33.0, -32.0, -32.9, -35.1, -34.2, -35.2, -37.5, -40.5, -42.6, -43.1, -42.0, -41.5, -46.3, -45.3, -40.9, -42.4, -48.3, -48.7, -43.5, -43.9, -48.3, -44.1, -46.4, -44.7, -42.7, -44.0, -46.2, -45.6, -46.2, -42.8, -38.9, -39.7, -39.1, -41.0, -40.7, -37.3, -34.4, -34.3, -35.1, -31.2, -28.8, -33.3, -33.4, -30.5, -29.1, -31.4, -34.7, -33.9, -34.6, -34.2, -35.3, -32.8, -33.3, -32.6, -37.5, -35.9, -34.9, -35.4, -33.0, -34.2, -33.4, -33.1, -37.7, -34.8, -37.3, -37.1, -39.3, -37.5, -39.0, -38.5, -40.6, -38.1, -37.8, -40.4, -38.6, -41.5, -41.3, -41.3, -42.5, -49.3], "hf": [0.98, 0.98, 0.98, 0.88, 0.74, 0.89, 0.67, 0.33, 0.14, 0.17, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.02, 0.02, 0.07, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.02, 0.01, 0.01, 0.29, 0.13, 0.12, 0.3, 0.23, 0.12, 0.05, 0.11, 0.21, 0.15, 0.11, 0.14, 0.11, 0.12, 0.07, 0.05, 0.02, 0.01, 0.01, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.03, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.01, 0.0, 0.01, 0.02, 0.02, 0.04, 0.02, 0.02, 0.03, 0.06, 0.06, 0.05, 0.13, 0.06, 0.03, 0.05, 0.01, 0.01, 0.03, 0.11, 0.02, 0.0, 0.03, 0.0, 0.0, 0.0, 0.01, 0.0, 0.03, 0.0, 0.01, 0.0, 0.01, 0.0, 0.04, 0.03, 0.02, 0.03, 0.01, 0.01, 0.01, 0.04, 0.03, 0.01, 0.01, 0.0, 0.03, 0.0, 0.01, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.01, 0.08, 0.0, 0.01, 0.01, 0.01, 0.0, 0.03, 0.01, 0.03, 0.0, 0.0, 0.01, 0.02, 0.14, 0.04, 0.01, 0.01, 0.11, 0.38, 0.06, 0.5, 0.15, 0.08, 0.02, 0.11, 0.16, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.02, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.01, 0.01, 0.01, 0.05, 0.01, 0.01, 0.0, 0.03, 0.02, 0.03, 0.01, 0.01, 0.01, 0.01, 0.02, 0.02, 0.01, 0.01, 0.01, 0.01, 0.02, 0.01, 0.0, 0.0, 0.0, 0.01, 0.03, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.01, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.01, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.02, 0.05, 0.09, 0.41, 0.61, 0.67, 0.81, 0.93, 0.97, 0.93, 0.88, 0.92, 0.99, 0.99, 0.99, 0.95, 0.98, 0.99, 0.98, 0.99, 0.99, 0.99, 0.97, 0.99, 0.99, 0.99, 0.99, 1.0, 0.99, 1.0, 0.99, 0.99, 0.99, 0.99, 0.99, 1.0, 1.0, 1.0, 0.99, 0.98, 0.98, 0.98, 0.98, 0.94, 0.75, 0.61, 0.81, 0.14, 0.01, 0.01, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.01, 0.01, 0.03, 0.05, 0.01, 0.02, 0.04, 0.04, 0.04, 0.04, 0.02, 0.04, 0.06, 0.14, 0.11, 0.13, 0.14, 0.09, 0.16, 0.16, 0.12, 0.16, 0.17, 0.4, 0.1, 0.13, 0.44, 0.24, 0.14, 0.09, 0.26, 0.08, 0.15, 0.34, 0.19, 0.08, 0.55, 0.13, 0.07, 0.18, 0.18, 0.09, 0.13, 0.38, 0.07, 0.12, 0.12, 0.1, 0.02, 0.02, 0.09, 0.02, 0.03, 0.11, 0.02, 0.03, 0.08, 0.05, 0.07, 0.09, 0.26, 0.06, 0.09, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.0, 0.0, 0.01, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.02, 0.02, 0.02, 0.01, 0.01, 0.01, 0.0, 0.01, 0.03, 0.03, 0.01, 0.04, 0.05, 0.06, 0.02, 0.01, 0.01, 0.17, 0.17, 0.14, 0.08, 0.14, 0.06, 0.14, 0.05, 0.09, 0.08, 0.17, 0.08, 0.16, 0.05, 0.2, 0.19, 0.06, 0.02, 0.28, 0.01, 0.05, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.01, 0.01, 0.01, 0.0, 0.0, 0.0, 0.01, 0.01, 0.01, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.02, 0.03, 0.01, 0.01, 0.01, 0.1, 0.0, 0.0, 0.02, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.01, 0.0, 0.0, 0.01, 0.02, 0.04, 0.09, 0.1, 0.07, 0.05, 0.04, 0.03, 0.08, 0.02, 0.07, 0.09, 0.1, 0.05, 0.05, 0.05, 0.08, 0.11, 0.13, 0.25, 0.03, 0.12, 0.01, 0.01, 0.04, 0.05, 0.02, 0.02, 0.04, 0.04, 0.05, 0.01, 0.07, 0.03, 0.01, 0.01, 0.03, 0.03, 0.05, 0.06, 0.02, 0.06, 0.02, 0.01, 0.0, 0.02, 0.01, 0.01, 0.01, 0.01, 0.0, 0.02, 0.02, 0.05, 0.0, 0.01, 0.01, 0.0, 0.0, 0.0, 0.01, 0.01, 0.05, 0.01, 0.09, 0.02, 0.03, 0.05, 0.03, 0.01, 0.05, 0.18, 0.13, 0.19, 0.22, 0.04, 0.05, 0.11, 0.11, 0.03, 0.08, 0.38, 0.16, 0.38, 0.07, 0.03, 0.0, 0.0, 0.01, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.01, 0.04, 0.02, 0.01, 0.02, 0.02, 0.02, 0.03, 0.04, 0.04, 0.09, 0.07, 0.1, 0.09, 0.2, 0.25, 0.41, 0.08, 0.09, 0.03, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.01, 0.01, 0.04, 0.04, 0.02, 0.01, 0.01, 0.02, 0.02, 0.03, 0.04, 0.05, 0.04, 0.05, 0.04, 0.05, 0.08, 0.11, 0.09, 0.23, 0.23, 0.11, 0.16, 0.29, 0.27, 0.27, 0.34, 0.68, 0.85, 0.87, 0.95, 0.95, 0.96, 0.98, 0.99, 0.98, 0.99, 0.98, 0.99, 0.99, 0.99, 0.98, 0.99, 0.97, 0.99, 0.99, 0.99, 0.99, 0.99, 0.99, 1.0, 0.99, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.99, 0.94, 0.98, 0.98, 0.97, 0.95, 0.88, 0.94, 0.82, 0.7, 0.82, 0.82, 0.68, 0.61, 0.47, 0.81, 0.58, 0.27, 0.83, 0.98, 0.98, 0.94, 0.6, 0.06, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.02, 0.01, 0.0, 0.01, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.01, 0.05, 0.02, 0.01, 0.02, 0.01, 0.0, 0.05, 0.01, 0.01, 0.01, 0.01, 0.0, 0.01, 0.0, 0.0, 0.01, 0.01, 0.01, 0.01, 0.0, 0.01, 0.03, 0.0, 0.0, 0.01, 0.01, 0.0, 0.02, 0.01, 0.01, 0.01, 0.02, 0.01, 0.01, 0.0, 0.01, 0.02, 0.03, 0.01, 0.01, 0.01, 0.02, 0.01, 0.01, 0.01, 0.02, 0.0, 0.0, 0.02, 0.0, 0.0, 0.02, 0.0, 0.01, 0.0, 0.0, 0.01, 0.0, 0.01, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.01, 0.0, 0.01, 0.01, 0.01, 0.01, 0.01, 0.17, 0.12, 0.01, 0.0, 0.01, 0.02, 0.0, 0.0, 0.01, 0.12, 0.01, 0.03, 0.01, 0.01, 0.05, 0.01, 0.01, 0.02, 0.0, 0.0, 0.02, 0.01, 0.01, 0.02, 0.12, 0.01, 0.0, 0.0, 0.01, 0.16, 0.18, 0.15, 0.32, 0.35, 0.23, 0.75, 0.83, 0.87, 0.88, 0.91, 0.9, 0.91, 0.91, 0.89, 0.85, 0.82, 0.91, 0.92, 0.9, 0.84, 0.82, 0.7, 0.74, 0.6, 0.41, 0.36, 0.02, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.01, 0.02, 0.04, 0.11, 0.39, 0.35, 0.4, 0.71, 0.4, 0.31, 0.55, 0.46, 0.86, 0.81, 0.92, 0.74, 0.7, 0.69, 0.87, 0.94, 0.87, 0.89, 0.61, 0.72, 0.49, 0.77, 0.66, 0.81, 0.98, 0.91, 0.87, 0.84, 0.46, 0.41, 0.87, 0.82, 0.86, 0.94, 0.9, 0.96, 0.82, 0.88, 0.76, 0.8, 0.49, 0.97, 0.93, 0.67, 0.87, 0.46, 0.87, 0.77, 0.56, 0.45, 0.16, 0.15, 0.43, 0.11, 0.04, 0.14, 0.13, 0.09, 0.13, 0.09, 0.2, 0.04, 0.01, 0.05, 0.01, 0.02, 0.04, 0.02, 0.58, 0.31, 0.71, 0.37, 0.32, 0.08, 0.38, 0.03, 0.01, 0.15, 0.1, 0.07, 0.2, 0.08, 0.01, 0.01, 0.22, 0.01, 0.0, 0.01, 0.01, 0.03, 0.0, 0.23, 0.08, 0.0, 0.0, 0.02, 0.0, 0.02, 0.0, 0.08, 0.0, 0.05, 0.01, 0.0, 0.01, 0.01, 0.09, 0.02, 0.13, 0.0, 0.02, 0.03, 0.04, 0.01, 0.18, 0.05, 0.01, 0.01, 0.02, 0.18, 0.13, 0.02, 0.01, 0.03, 0.05, 0.03, 0.01, 0.03, 0.01, 0.05, 0.04, 0.13, 0.05, 0.5, 0.14, 0.04, 0.09, 0.23, 0.63, 0.16, 0.08, 0.09, 0.83, 0.1, 0.12, 0.16, 0.08, 0.03, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.01, 0.0, 0.01, 0.0, 0.01, 0.01, 0.0, 0.01, 0.0, 0.01, 0.01, 0.0, 0.01, 0.01, 0.02, 0.01, 0.02, 0.02, 0.01, 0.02, 0.01, 0.02, 0.01, 0.01, 0.02, 0.01, 0.02, 0.01, 0.01, 0.02, 0.01, 0.03, 0.01, 0.02, 0.02, 0.01, 0.03, 0.01, 0.02, 0.01, 0.01, 0.03, 0.01, 0.03, 0.01, 0.02, 0.02, 0.01, 0.03, 0.01, 0.02, 0.02, 0.01, 0.03, 0.01, 0.03, 0.01, 0.01, 0.03, 0.01, 0.03, 0.02, 0.01, 0.02, 0.02, 0.03, 0.02, 0.02, 0.03, 0.01, 0.03, 0.02, 0.02, 0.04, 0.02, 0.03, 0.02, 0.02, 0.02, 0.02, 0.02, 0.01, 0.01, 0.02, 0.01, 0.02, 0.01, 0.02, 0.01, 0.01, 0.03, 0.01, 0.03, 0.01, 0.01, 0.02, 0.0, 0.03, 0.01, 0.01, 0.02, 0.01, 0.03, 0.01, 0.02, 0.02, 0.0, 0.02, 0.01, 0.01, 0.02, 0.01, 0.01, 0.01, 0.0, 0.0, 0.0, 0.01, 0.01, 0.01, 0.01, 0.01, 0.02, 0.02, 0.01, 0.01, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.02, 0.01, 0.01, 0.03, 0.02, 0.01, 0.06, 0.01, 0.01, 0.04, 0.02, 0.01, 0.01, 0.01, 0.01, 0.03, 0.02, 0.01, 0.06, 0.03, 0.02, 0.06, 0.02, 0.02, 0.05, 0.02, 0.02, 0.08, 0.05, 0.03, 0.07, 0.05, 0.04, 0.09, 0.08, 0.04, 0.08, 0.07, 0.06, 0.06, 0.05, 0.04, 0.04, 0.02, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.01, 0.0, 0.01, 0.02, 0.01, 0.0, 0.01, 0.01, 0.0, 0.0, 0.01, 0.03, 0.01, 0.03, 0.01, 0.01, 0.02, 0.03, 0.01, 0.02, 0.01, 0.02, 0.01, 0.01, 0.0, 0.0, 0.01, 0.01, 0.01, 0.0, 0.02, 0.05, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.0, 0.02, 0.0, 0.0, 0.0, 0.0, 0.02, 0.01, 0.01, 0.0, 0.0, 0.01, 0.01, 0.01, 0.0, 0.0, 0.01, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.01, 0.01, 0.01, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.01, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.01, 0.01, 0.02, 0.02, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.02, 0.02, 0.03, 0.04, 0.04, 0.07, 0.07, 0.07, 0.11, 0.17, 0.06, 0.1, 0.17, 0.12, 0.1, 0.1, 0.19, 0.15, 0.11, 0.29, 0.16, 0.13, 0.09, 0.05, 0.04, 0.08, 0.09, 0.37, 0.08, 0.05, 0.21, 0.06, 0.1, 0.09, 0.1, 0.08, 0.11, 0.13, 0.17, 0.08, 0.14, 0.05, 0.06, 0.07, 0.04, 0.02, 0.03, 0.05, 0.05, 0.05, 0.01, 0.0, 0.03, 0.0, 0.0, 0.01, 0.03, 0.01, 0.04, 0.03, 0.02, 0.01, 0.06, 0.05, 0.14, 0.05, 0.01, 0.01, 0.47, 0.22, 0.39, 0.21, 0.48, 0.03, 0.21, 0.52, 0.72, 0.24, 0.05, 0.1, 0.1, 0.03, 0.01, 0.01, 0.02, 0.05, 0.04, 0.01, 0.35, 0.03, 0.2, 0.45, 0.27, 0.37, 0.14, 0.35, 0.41, 0.26, 0.15, 0.31, 0.08, 0.07, 0.01, 0.03, 0.01, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.02, 0.01, 0.01, 0.01, 0.0, 0.01, 0.01, 0.01, 0.01, 0.0, 0.01, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.01, 0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.02, 0.02, 0.02, 0.06, 0.1, 0.21, 0.27, 0.64, 0.78, 0.64, 0.88, 0.87, 0.75, 0.94, 0.96, 0.95, 0.92, 0.94, 0.96, 0.94, 0.92, 0.94, 0.9, 0.96, 0.98, 0.97, 0.91, 0.98, 0.94, 0.93, 0.97, 0.95, 0.96, 0.92, 0.92, 0.96, 0.86, 0.95, 0.92, 0.92, 0.96, 0.93, 0.49, 0.75, 0.28, 0.02, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.02, 0.01, 0.0, 0.01, 0.0, 0.01, 0.07, 0.01, 0.0, 0.01, 0.0, 0.01, 0.07, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.05, 0.0, 0.01, 0.01, 0.04, 0.04, 0.01, 0.01, 0.01, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.03, 0.01, 0.02, 0.01, 0.0, 0.01, 0.0, 0.0, 0.01, 0.0, 0.01, 0.01, 0.01, 0.0, 0.0, 0.0, 0.02, 0.02, 0.04, 0.1, 0.13, 0.31, 0.19, 0.24, 0.18, 0.21, 0.44, 0.24, 0.43, 0.45, 0.25, 0.24, 0.16, 0.27, 0.44, 0.22, 0.14, 0.19, 0.16, 0.21, 0.32, 0.1, 0.13, 0.21, 0.09, 0.16, 0.07, 0.16, 0.18, 0.07, 0.01, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.01, 0.01, 0.0, 0.01, 0.01, 0.01, 0.01, 0.01, 0.02, 0.01, 0.01, 0.02, 0.0, 0.03, 0.01, 0.02, 0.01, 0.01, 0.03, 0.01, 0.03, 0.02, 0.01, 0.02, 0.01, 0.03, 0.01, 0.01, 0.02, 0.01, 0.02, 0.01, 0.01, 0.02, 0.02, 0.03, 0.01, 0.02, 0.01, 0.02, 0.02, 0.01, 0.03, 0.02, 0.03, 0.02, 0.01, 0.02, 0.01, 0.02, 0.02, 0.01, 0.03, 0.01, 0.02, 0.02, 0.02, 0.03, 0.03, 0.03, 0.02, 0.01, 0.02, 0.01, 0.01, 0.01, 0.01, 0.02, 0.01, 0.02, 0.01, 0.01, 0.01, 0.01, 0.02, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.02, 0.01, 0.02, 0.01, 0.01, 0.01, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.02, 0.01, 0.0, 0.01, 0.04, 0.02, 0.01, 0.03, 0.03, 0.03, 0.05, 0.03, 0.12, 0.14, 0.27, 0.28, 0.56, 0.7, 0.49, 0.74, 0.9, 0.87, 0.86, 0.81, 0.91, 0.93, 0.71, 0.53, 0.54, 0.7, 0.6, 0.67, 0.56, 0.6, 0.63, 0.48, 0.35, 0.37, 0.22, 0.33, 0.42, 0.45, 0.37, 0.16, 0.14, 0.29, 0.25, 0.52, 0.21, 0.14, 0.03, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.03, 0.0, 0.0, 0.0, 0.01, 0.01, 0.21, 0.74, 0.97, 0.89, 0.99, 0.98, 0.85, 0.89, 0.88, 0.47, 0.7, 0.46, 0.41, 0.62, 0.34, 0.33, 0.35, 0.39, 0.45, 0.42, 0.5, 0.22, 0.16, 0.33, 0.18, 0.27, 0.12, 0.24, 0.12, 0.2, 0.13, 0.27, 0.11, 0.05, 0.01, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.01, 0.0, 0.02, 0.02, 0.04, 0.0, 0.0, 0.02, 0.0, 0.0, 0.0, 0.0, 0.0, 0.02, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.02, 0.01, 0.08, 0.01, 0.01, 0.05, 0.01, 0.01, 0.01, 0.01, 0.03, 0.03, 0.03, 0.01, 0.02, 0.01, 0.01, 0.01, 0.02, 0.07, 0.03, 0.01, 0.03, 0.02, 0.03, 0.02, 0.0, 0.0, 0.0, 0.01, 0.0, 0.01, 0.0, 0.0, 0.02, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.01, 0.01, 0.02, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.01, 0.01, 0.02, 0.01, 0.02, 0.03, 0.04, 0.0, 0.0, 0.19, 0.02, 0.03, 0.01, 0.01, 0.03, 0.02, 0.01, 0.0, 0.01, 0.01, 0.01, 0.56, 0.96, 0.98, 0.98, 0.88, 0.79, 0.99, 0.88, 0.91, 0.82, 0.93, 0.73, 0.82, 0.84, 0.57, 0.65, 0.71, 0.57, 0.55, 0.54, 0.38, 0.43, 0.61, 0.34, 0.34, 0.18, 0.1, 0.03, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.01, 0.01, 0.01, 0.01, 0.0, 0.01, 0.0, 0.01, 0.0, 0.01, 0.01, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.01, 0.01, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.01, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.01, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.02, 0.02, 0.01, 0.0, 0.0, 0.0, 0.02, 0.0, 0.0, 0.01, 0.02, 0.0, 0.02, 0.0, 0.0, 0.01, 0.02, 0.0, 0.0, 0.02, 0.0, 0.02, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.01, 0.0, 0.0, 0.03, 0.0, 0.0, 0.02, 0.05, 0.01, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.02, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.02, 0.01, 0.01, 0.01, 0.01, 0.02, 0.0, 0.0, 0.0, 0.0, 0.02, 0.03, 0.02, 0.02, 0.01, 0.0, 0.0, 0.08, 0.01, 0.01, 0.03, 0.04, 0.03, 0.1, 0.03, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.01, 0.0, 0.05, 0.0, 0.01, 0.0, 0.02, 0.0, 0.0, 0.03, 0.03, 0.01, 0.14, 0.01, 0.0, 0.01, 0.06, 0.01, 0.0, 0.0, 0.01, 0.0, 0.02, 0.03, 0.03, 0.07, 0.14, 0.06, 0.12, 0.15, 0.04, 0.15, 0.22, 0.11, 0.44, 0.39, 0.14, 0.19, 0.1, 0.19, 0.27, 0.08, 0.17, 0.12, 0.15, 0.17, 0.09, 0.16, 0.14, 0.05, 0.05, 0.08, 0.03, 0.03, 0.03, 0.01, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.03, 0.0, 0.0, 0.03, 0.0, 0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.02, 0.01, 0.01, 0.05, 0.03, 0.38, 0.4, 0.84, 0.46, 0.23, 0.64, 0.93, 0.91, 0.68, 0.7, 0.99, 0.93, 0.94, 0.96, 1.0, 1.0, 0.99, 0.99, 0.99, 0.97, 0.98, 0.96, 0.91, 0.98, 0.95, 0.98, 0.99, 0.96, 0.98, 0.96, 0.99, 0.98, 0.96, 0.99, 0.99, 0.94, 0.98, 0.98, 0.99, 0.96, 0.99, 0.81, 0.86, 0.97, 0.97, 0.94, 0.98, 0.99, 0.98, 1.0, 0.98, 0.92, 0.68, 0.74, 0.91]}}}} \ No newline at end of file