package com.example.data.mediastore import android.content.Context import android.net.Uri import com.example.data.model.MediaItemData import java.io.File import java.io.FileOutputStream import java.nio.ByteBuffer import java.nio.ByteOrder import kotlin.math.sin object DemoMediaProvider { fun getOrCreateDemoMedia(context: Context): List { val sampleDir = File(context.filesDir, "swipeplay_samples") if (!sampleDir.exists()) { sampleDir.mkdirs() } val sampleFiles = listOf( SampleTrackSpec("Neon Horizon", "Synthwave Club", "Night Drive", 140.0, 18, 440.0), SampleTrackSpec("Violet Pulse", "Amoled Beats", "Dark Frequencies", 124.0, 24, 523.25), SampleTrackSpec("Midnight Echoes", "Lunar Echo", "Starlight EP", 110.0, 20, 329.63), SampleTrackSpec("Electric Drift", "Cyber Drift", "Velocity", 132.0, 16, 392.0), SampleTrackSpec("Deep Ambient Space", "Zenith", "Silent Cosmos", 85.0, 22, 261.63) ) val items = mutableListOf() sampleFiles.forEachIndexed { index, spec -> val file = File(sampleDir, "sample_audio_${index + 1}.wav") if (!file.exists() || file.length() < 1000) { generatePlayableWav(file, spec.bpm, spec.durationSec, spec.baseFreq) } val uri = Uri.fromFile(file).toString() items.add( MediaItemData( id = "demo_audio_${index + 1}", contentUri = uri, title = spec.title, artist = spec.artist, album = spec.album, durationMs = (spec.durationSec * 1000).toLong(), mimeType = "audio/wav", isVideo = false, sizeBytes = file.length(), dateAdded = System.currentTimeMillis() - (index * 86400000L), folderName = "Demo Samples", relativePath = "SwipePlay/Samples" ) ) } return items } private data class SampleTrackSpec( val title: String, val artist: String, val album: String, val bpm: Double, val durationSec: Int, val baseFreq: Double ) /** * Generates a standard PCM 16-bit 44.1kHz mono WAV file with synth melodies, chords, and rhythmic kick pulses. */ private fun generatePlayableWav(outputFile: File, bpm: Double, durationSec: Int, baseFreq: Double) { try { val sampleRate = 44100 val numSamples = sampleRate * durationSec val pcmData = ShortArray(numSamples) val beatDuration = (60.0 / bpm) * sampleRate for (i in 0 until numSamples) { val t = i.toDouble() / sampleRate val beatPos = (i % beatDuration.toInt()).toDouble() / beatDuration // Melody note shifting every 2 beats val measure = (i / (beatDuration * 2)).toInt() % 4 val chordMultiplier = when (measure) { 0 -> 1.0 1 -> 1.25 // Major 3rd 2 -> 1.5 // Perfect 5th else -> 1.333 // 4th } // Synth lead tone val tone = sin(2.0 * Math.PI * (baseFreq * chordMultiplier) * t) * 0.35 val harmonic = sin(4.0 * Math.PI * (baseFreq * chordMultiplier) * t) * 0.15 // Kick drum on each beat (exponential decay frequency drop) val kickDecay = Math.exp(-beatPos * 8.0) val kickFreq = 150.0 * Math.exp(-beatPos * 25.0) + 45.0 val kick = sin(2.0 * Math.PI * kickFreq * beatPos) * kickDecay * 0.45 // Snare / clap on alternate beats val isAlternateBeat = ((i / beatDuration.toInt()) % 2) == 1 val snare = if (isAlternateBeat) { val snareDecay = Math.exp(-beatPos * 14.0) val noise = ((Math.random() * 2.0) - 1.0) * 0.18 * snareDecay noise } else 0.0 val mixed = (tone + harmonic + kick + snare).coerceIn(-1.0, 1.0) pcmData[i] = (mixed * 32767.0).toInt().toShort() } writeWavFile(outputFile, sampleRate, pcmData) } catch (_: Exception) { } } private fun writeWavFile(file: File, sampleRate: Int, samples: ShortArray) { val totalAudioLen = samples.size * 2 val totalDataLen = totalAudioLen + 36 val byteRate = sampleRate * 2 FileOutputStream(file).use { out -> val header = ByteBuffer.allocate(44).order(ByteOrder.LITTLE_ENDIAN) header.put("RIFF".toByteArray(Charsets.US_ASCII)) header.putInt(totalDataLen) header.put("WAVE".toByteArray(Charsets.US_ASCII)) header.put("fmt ".toByteArray(Charsets.US_ASCII)) header.putInt(16) // Subchunk1Size header.putShort(1) // AudioFormat (PCM) header.putShort(1) // NumChannels (Mono) header.putInt(sampleRate) header.putInt(byteRate) header.putShort(2) // BlockAlign header.putShort(16) // BitsPerSample header.put("data".toByteArray(Charsets.US_ASCII)) header.putInt(totalAudioLen) out.write(header.array()) val buffer = ByteBuffer.allocate(samples.size * 2).order(ByteOrder.LITTLE_ENDIAN) for (sample in samples) { buffer.putShort(sample) } out.write(buffer.array()) out.flush() } } }