# Project export: MixMate

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: TreeHacks 2026
- Tagline: MixMate is the only tool for live audio engineers that provides instant mix fixes, AI-powered insights, and generates seamless intermission music using Suno, Claude, and real-time audio analysis.
- Devpost: https://devpost.com/software/mixmate
- GitHub: https://github.com/Rahuuuul/TreeHacks-26-Public/
- Video: https://www.youtube.com/embed/3st3aC7NYA8?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 0 GitHub contributor(s) — 

## Devpost submission (written by the team)

### Inspiration

MixMate was inspired by our experience in live sound engineering. Spending hours mixing live performances, we often encountered recurring challenges: feedback, inaudible singers, harsh frequencies, and the pressure of keeping audiences engaged. Existing tools provided either raw visualisation or basic analysis, leaving a gap for actionable, intelligent guidance. MixMate was built to fill this gap, combining audio analysis with AI-driven insights and intermission music generation. What It Does MixMate empowers live audio engineers by providing: Real-Time Audio Analysis - Visualise and monitor every frequency band during live shows or with prerecorded tracks. Raw Mix Insights - Identify muddiness, harsh highs, and tonal imbalances, giving a clear overview of the mix. AI-Powered Recommendations - Claude analyses the audio and generates precise EQ, compression, and mix adjustment suggestions tailored to the venue and setup. Intermission Music Generation - Suno creates seamless, vibe-matched instrumental tracks inspired by the previous track, keeping audiences engaged between sets. How We Built It Audio Engine & Analysis: AVAudioEngine with FFT-based feature extraction to deliver live and offline audio analysis with minimal latency. AI Integration: Structured prompts for Claude and Suno to produce recommendations and musical intermission tracks. User Interface: Built in SwiftUI, the dashboard displays frequency spectra, detected issues, AI insights, and generated prompts intuitively. Accomplishments Developed a robust real-time audio analyser capable of functioning in live venues of all sizes, and across various music genres. Created a reliable Claude prompt system for actionable mix recommendations. Integrated Suno intermission music generation directly into the app workflow. Integrated Suno intermission music generation directly into the app workflow. Designed a unified dashboard that displays the Real-Time Analyser, AI insights, and generated music prompts in one place. What's Next! Expanding AI recommendations to support complex multi-instrument setups. Developing venue-adaptive recommendations, adjusting based on acoustics and audience size. Offering customisable intermission music styles, including genre, tempo, and mood options. Conducting more in-depth music analysis to confirm the key, genre, and tempo of each input. Launching cross-platform support for macOS, Android, and integration with live sound consoles (DiGiCo, Yamaha, Allen & Heath).

## README (from the GitHub repository)

No README available.

## Detected evidence (automated analysis)

Indexed codebase: 19 recognized source files, 61 KB.
- Swift (language) — detected in the code

## Codebase structure (from repository index)

### Files (27 of 27)

```
AudioAIApp/AudioAIApp.xcodeproj/project.pbxproj
AudioAIApp/AudioAIApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata
AudioAIApp/AudioAIApp.xcodeproj/project.xcworkspace/xcuserdata/rahulk.xcuserdatad/UserInterfaceState.xcuserstate
AudioAIApp/AudioAIApp.xcodeproj/xcuserdata/rahulk.xcuserdatad/xcschemes/xcschememanagement.plist
AudioAIApp/AudioAIApp/AI/ClaudeResponses.swift
AudioAIApp/AudioAIApp/AI/ClaudeService.swift
AudioAIApp/AudioAIApp/AI/SunoClient.swift
AudioAIApp/AudioAIApp/Assets.xcassets/AccentColor.colorset/Contents.json
AudioAIApp/AudioAIApp/Assets.xcassets/AppIcon.appiconset/Contents.json
AudioAIApp/AudioAIApp/Assets.xcassets/Contents.json
AudioAIApp/AudioAIApp/Audio/AudioEngineManager.swift
AudioAIApp/AudioAIApp/Audio/FeatureExtractor.swift
AudioAIApp/AudioAIApp/Audio/FFTProcessor.swift
AudioAIApp/AudioAIApp/Audio/IssueDetector.swift
AudioAIApp/AudioAIApp/Audio/MixContext.swift
AudioAIApp/AudioAIApp/AudioAIApp.entitlements
AudioAIApp/AudioAIApp/AudioAIAppApp.swift
AudioAIApp/AudioAIApp/UI/ContentView.swift
AudioAIApp/AudioAIApp/UI/ContextInfoView.swift
AudioAIApp/AudioAIApp/UI/ControlsView.swift
AudioAIApp/AudioAIApp/UI/IssueListView.swift
AudioAIApp/AudioAIApp/UI/SettingsView.swift
AudioAIApp/AudioAIApp/UI/SpectrumView.swift
AudioAIApp/AudioAIApp/UI/SunoGeneratorView.swift
AudioAIApp/AudioAIAppTests/AudioAIAppTests.swift
AudioAIApp/AudioAIAppUITests/AudioAIAppUITests.swift
AudioAIApp/AudioAIAppUITests/AudioAIAppUITestsLaunchTests.swift
```

### Dependencies

No dependency index available.

### Recent commits (newest first)

- Add files via upload

## Key source files (fetched from GitHub, selected and truncated for size)

### AudioAIApp/AudioAIAppTests/AudioAIAppTests.swift

```swift
//
//  AudioAIAppTests.swift
//  AudioAIAppTests
//
//  Created by Rahul Kumar on 14/2/2026.
//

import Testing

struct AudioAIAppTests {

    @Test func example() async throws {

    }

}

```

### AudioAIApp/AudioAIApp/AudioAIAppApp.swift

```swift
//
//  AudioAIAppApp.swift
//  AudioAIApp
//
//  Created by Rahul Kumar on 14/2/2026.
//

import SwiftUI

@main
struct AudioAIAppApp: App {
    @StateObject private var audioManager = AudioEngineManager()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(audioManager)
        }
    }
}

```

### AudioAIApp/AudioAIAppUITests/AudioAIAppUITests.swift

```swift
//
//  AudioAIAppUITests.swift
//  AudioAIAppUITests
//
//  Created by Rahul Kumar on 14/2/2026.
//

import XCTest

final class AudioAIAppUITests: XCTestCase {

    override func setUpWithError() throws {

        continueAfterFailure = false

    }

    override func tearDownWithError() throws {
    }

    @MainActor
    func testExample() throws {
        let app = XCUIApplication()
        app.launch()

    }

    @MainActor
    func testLaunchPerformance() throws {
        measure(metrics: [XCTApplicationLaunchMetric()]) {
            XCUIApplication().launch()
        }
    }
}

```

### AudioAIApp/AudioAIAppUITests/AudioAIAppUITestsLaunchTests.swift

```swift
//
//  AudioAIAppUITestsLaunchTests.swift
//  AudioAIAppUITests
//
//  Created by Rahul Kumar on 14/2/2026.
//

import XCTest

final class AudioAIAppUITestsLaunchTests: XCTestCase {

    override class var runsForEachTargetApplicationUIConfiguration: Bool {
        true
    }

    override func setUpWithError() throws {
        continueAfterFailure = false
    }

    @MainActor
    func testLaunch() throws {
        let app = XCUIApplication()
        app.launch()


        let attachment = XCTAttachment(screenshot: app.screenshot())
        attachment.name = "Launch Screen"
        attachment.lifetime = .keepAlways
        add(attachment)
    }
}

```

### AudioAIApp/AudioAIApp/AI/ClaudeResponses.swift

```swift
//
//  ClaudeResponses.swift
//  AudioAIApp
//
//  Created by Rahul Kumar on 15/2/2026.
//

import Foundation

struct AIAnalysisResponse: Codable {
    let prompt_1: SunoPrompt
    let prompt_2: MixRecommendations
}

struct SunoPrompt: Codable {
    let suno_prompt: String
    let tags: [String]
    let title: String
}

struct MixRecommendations: Codable {
    let diagnosis: String
    let eq_suggestions: [EQSuggestion]
    let explanation: String
}

struct EQSuggestion: Codable {
    let frequency_hz: Double
    let adjustment_db: Double
    let q: Double
    let target: String
}

```

### AudioAIApp/AudioAIApp/UI/SpectrumView.swift

```swift
//
//  SpectrumView.swift
//  AudioAIApp
//
//  Created by Rahul Kumar on 14/2/2026.
//

import SwiftUI
import Charts


struct SpectrumView: View {
    @EnvironmentObject var audio: AudioEngineManager


    func getFrequencyLabel(for index: Int) -> String? {
        let labeledBands: [Int: String] = [
            0: "20 Hz",
            3: "100 Hz",
            7: "200 Hz",
            12: "400 Hz",
            16: "600 Hz",
            20: "800 Hz",
            22: "1 kHz",
            27: "2 kHz",
            32: "4 kHz",
            36: "6 kHz",
            40: "8 kHz",
            42: "10 kHz",
            47: "20 kHz",
        ]
        return labeledBands[index]
    }

    var body: some View {
        Chart {
            ForEach(Array(audio.spectrum.enumerated()), id: \.offset) { index, value in
                BarMark(
                    x: .value("Band", index),
                    y: .value("Magnitude", value),
                    width: .fixed(10)
                )
                .foregroundStyle(.blue)
                .annotation(position: .bottom) {
                    if let label = getFrequencyLabel(for: index) {
                        Text(label)
                            .font(.caption2)
                    }
                }
            }
        }
        .chartXScale(
            domain: 0...(max(audio.spectrum.count - 1, 0))
        )
        .chartXAxis(.hidden)
        .chartYScale(domain: 0...1)
        .frame(height: 300)
        .padding()
    }
}

```

### AudioAIApp/AudioAIApp/UI/ContentView.swift

```swift
//
//  ContentView.swift
//  AudioAIApp
//
//  Created by Rahul Kumar on 14/2/2026.
//

import SwiftUI

struct ContentView: View {
    @EnvironmentObject var audio: AudioEngineManager
    
    @State private var showFilePicker = false
    @State private var showSettings = false
    
    var body: some View {
        ScrollView {
            VStack(spacing: 20) {
                // Header controls
                ControlsView(
                    showFilePicker: $showFilePicker,
                    showSettings: $showSettings
                )
                .environmentObject(audio)
                
                // Context info display
                if !showSettings {
                    ContextInfoView(context: audio.mixContext)
                }
                
                // Settings panel
                if showSettings {
                    SettingsView(context: $audio.mixContext)
                        .transition(.move(edge: .top).combined(with: .opacity))
                }
                
                // Spectrum analyzer
                SpectrumView()
                    .environmentObject(audio)
                
                // Issue display
                if !audio.detectedIssues.isEmpty {
                    IssuesListView(
                        issues: audio.detectedIssues,
                        analysis: audio.currentAnalysis
                    )                }
                
                SunoGeneratorView()
                

            }
            .padding()
            .animation(.easeInOut, value: showSettings)
            .fileImporter(
                isPresented: $showFilePicker,
                allowedContentTypes: [.mp3, .audio],
                allowsMultipleSelection: false
            ) { result in
                handleFileImport(result)
            }
        }
    }
    
    // MARK: Helper Methods
    
    private func handleFileImport(_ result: Result<[URL], Error>) {
        switch result {
        case .success(let urls):
            if let url = urls.first {
                _ = url.startAccessingSecurityScopedResource()
                audio.useFile(url: url)
            }
        case .failure(let error):
            print("File picker error: \(error)")
        }
    }
}

```

### AudioAIApp/AudioAIApp/UI/ContextInfoView.swift

```swift
//
//  ContextInfoView.swift
//  AudioAIApp
//
//  Created by Rahul Kumar on 14/2/2026.
//

import SwiftUI

struct ContextInfoView: View {
    let context: MixContext
    
    // MARK: Computed Properties for Genres
    private var genreDisplay: String {
        if context.selectedGenres.isEmpty {
            return "No Genre"
        }
        return context.selectedGenres
            .map { $0.rawValue }
            .sorted()
            .joined(separator: "/")
    }
    
    var body: some View {
        HStack(spacing: 8) {
            HStack(spacing: 4) {
                Image(systemName: "info.circle")
                    .font(.system(size: 10))
                
                Text("\(context.setupType.rawValue) • \(genreDisplay) • \(context.venueSize.capacity)")
                    .font(.caption)
                    .lineLimit(1)
                    .truncationMode(.tail)
            }
            .foregroundColor(.secondary)
            
            Spacer()
            
            HStack(spacing: 4) {
                Image(systemName: sensitivityIcon)
                    .font(.caption2)
                Text(sensitivityLabel)
                    .font(.caption2)
                    .fontWeight(.bold)
            }
            .foregroundColor(sensitivityColor)
            .padding(.horizontal, 8)
            .padding(.vertical, 2)
            .background(sensitivityColor.opacity(0.1))
            .cornerRadius(4)
        }
        .padding(.horizontal)
        .padding(.vertical, 4)
    }
    
    // MARK: Sensitivity Helpers
    
    private var sensitivityIcon: String {
        switch context.sensitivity {
        case .relaxed: return "gauge.with.needle.low"
        case .moderate: return "gauge.with.needle.medium"
        case .strict: return "gauge.with.needle.high"
        case .veryStrict: return "exclamationmark.shield.fill"
        }
    }
    
    private var sensitivityLabel: String {
        switch context.sensitivity {
        case .relaxed: return "Relaxed"
        case .moderate: return "Moderate"
        case .strict: return "Strict"
        case .veryStrict: return "Very Strict"
        }
    }
    
    private var sensitivityColor: Color {
        switch context.sensitivity {
        case .relaxed: return .green
        case .moderate: return .blue
        case .strict: return .orange
        case .veryStrict: return .red
        }
    }
}

```

### AudioAIApp/AudioAIApp/UI/SettingsView.swift

```swift
//
//  SettingsView.swift
//  AudioAIApp
//
//  Created by Rahul Kumar on 14/2/2026.
//

import SwiftUI

struct SettingsView: View {
    @Binding var context: MixContext
    
    var body: some View {
        VStack(alignment: .leading, spacing: 20) {
            Text("Mix Context")
                .font(.headline)
            
            ScrollView {
                VStack(alignment: .leading, spacing: 16) {
                    
                    contextSection(title: "Setup Type") {
                        Picker("Setup", selection: $context.setupType) {
                            ForEach(SetupType.allCases) { type in
                                Text(type.rawValue).tag(type)
                            }
                        }
                        .pickerStyle(.menu)
                    }
                    
                    
                    contextSection(title: "Venue Size") {
                        Picker("Venue", selection: $context.venueSize) {
                            ForEach(VenueSize.allCases) { venue in
                                Text(venue.rawValue).tag(venue)
                            }
                        }
                        .pickerStyle(.menu)
                    }
                    
                    contextSection(title: "Analysis Sensitivity") {
                        Picker("Sensitivity", selection: $context.sensitivity) {
                            ForEach(AnalysisSensitivity.allCases) { sensitivity in
                                Text(sensitivity.rawValue).tag(sensitivity)
                            }
                        }
                        .pickerStyle(.menu)
                        
                        Text(context.sensitivity.description)
                            .font(.caption2)
                            .foregroundColor(.secondary)
                            .italic()
                    }
                }
            }
        }
        .padding()
        .background(Color(.systemBackground))
        .cornerRadius(12)
        .shadow(radius: 2)
        .padding(.horizontal)
    }
    
    
    
    private func contextSection<Content: View>(title: String, @ViewBuilder content: () -> Content) -> some View {
        VStack(alignment: .leading, spacing: 4) {
            Text(title)
                .font(.caption)
                .foregroundColor(.secondary)
            content()
        }
    }
}


```

### AudioAIApp/AudioAIApp/Audio/FeatureExtractor.swift

```swift
//
//  FeatureExtractor.swift
//  AudioAIApp
//
//  Created by Rahul Kumar on 14/2/2026.
//

import Foundation

struct FrequencyBands {
    var subBass: Float       // 20-60 Hz - Deep rumble, sub frequencies
    var bass: Float          // 60-120 Hz - Kick drum fundamental
    var lowMids: Float       // 120-250 Hz - Muddiness range, bass body
    var lowerMids: Float     // 250-500 Hz - Boxiness, warmth
    var mids: Float          // 500-1000 Hz - Body, fundamental vocals
    var upperMids: Float     // 1000-2000 Hz - Vocal clarity, definition
    var presence: Float      // 2000-4000 Hz - Vocal presence, attack
    var brightness: Float    // 4000-6000 Hz - Clarity, edge
    var brilliance: Float    // 6000-10000 Hz - Sibilance, cymbals
    var air: Float           // 10000-20000 Hz - Air, sparkle, openness
}

final class FeatureExtractor {
    
    // Extract from your 48 custom bands directly
    func extract(from spectrum: [Float]) -> FrequencyBands {
        guard spectrum.count == 48 else {
            return FrequencyBands(
                subBass: 0, bass: 0, lowMids: 0, lowerMids: 0, mids: 0,
                upperMids: 0, presence: 0, brightness: 0, brilliance: 0, air: 0
            )
        }
        
        
        let subBass = average(spectrum, from: 0, to: 2)      // 20-70 Hz
        let bass = average(spectrum, from: 3, to: 6)         // 100-175 Hz
        let lowMids = average(spectrum, from: 7, to: 9)      // 200-280 Hz
        let lowerMids = average(spectrum, from: 10, to: 14)  // 320-500 Hz
        let mids = average(spectrum, from: 15, to: 21)       // 550-900 Hz
        let upperMids = average(spectrum, from: 22, to: 26)  // 1000-1800 Hz
        let presence = average(spectrum, from: 27, to: 31)   // 2000-3600 Hz
        let brightness = average(spectrum, from: 32, to: 35) // 4000-5500 Hz
        let brilliance = average(spectrum, from: 36, to: 41) // 6000-9000 Hz
        let air = average(spectrum, from: 42, to: 47)        // 10000-20000 Hz
        
        return FrequencyBands(
            subBass: subBass,
            bass: bass,
            lowMids: lowMids,
            lowerMids: lowerMids,
            mids: mids,
            upperMids: upperMids,
            presence: presence,
            brightness: brightness,
            brilliance: brilliance,
            air: air
        )
    }
    
    private func average(_ spectrum: [Float], from start: Int, to end: Int) -> Float {
        let slice = spectrum[start...end]
        return slice.reduce(0, +) / Float(slice.count)
    }
}

```

[9 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]