# Playing a simple MP3 file

**URL:** <https://openrndr.discourse.group/t/playing-a-simple-mp3-file/690>\
**Category:** Tutorials\
**Created:** [October 4, 2024, 3:23pm UTC](https://openrndr.discourse.group/t/playing-a-simple-mp3-file/690 "2024-10-04T15:23:48Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![dedos](https://avatars.discourse-cdn.com/v4/letter/d/f07891/32.png) [@dedos](https://openrndr.discourse.group/u/dedos)\
**Post date:** [October 4, 2024, 3:23pm UTC](https://openrndr.discourse.group/t/playing-a-simple-mp3-file/690/1 "2024-10-04T15:23:48Z")

</div>

I’m working on a project that has to load a MP3 file and play it along with loaded images and videos. I stumped on the fact that OPENRNDR doesn’t handle MP3 files and came up with a workaround. I don’t think this is the ideal solution, but it works.

In `build.gradle.kts` we should add:

```auto
plugins {
    id("org.openjfx.javafxplugin") version "0.1.0"
}

javafx {
    version = "22.0.1"
}

```

And here is the code for a simple program that plays the audio file. Note that as JavaFX doesn’t have native MP3 support, I’m using FFmpeg to convert the MP3 file to a WAV file and play it.

The program also checks if there is already a WAV file with the same name of the MP3 file. If there is, it plays the WAV file directly, without converting.

```auto
import org.openrndr.application
import javax.sound.sampled.*
import java.io.File
import java.io.IOException
import kotlin.concurrent.thread

class AudioPlayer(private val mp3FilePath: String) {
    private var clip: Clip? = null
    private var isPlaying = false
    private val wavFilePath: String

    init {
        val mp3File = File(mp3FilePath)
        wavFilePath = mp3File.parent + File.separator + mp3File.nameWithoutExtension + ".wav"
    }

    fun play() {
        if (!isPlaying) {
            thread {
                try {
                    if (!File(wavFilePath).exists()) {
                        convertToWav()
                    }

                    val audioInputStream = AudioSystem.getAudioInputStream(File(wavFilePath))
                    clip = AudioSystem.getClip()
                    clip?.open(audioInputStream)
                    clip?.start()
                    isPlaying = true
                    println("Playing audio: $wavFilePath")
                    clip?.addLineListener { event ->
                        if (event.type == LineEvent.Type.STOP) {
                            isPlaying = false
                            clip?.close()
                            println("Audio playback finished")
                        }
                    }
                } catch (e: Exception) {
                    println("Error playing audio: ${e.message}")
                    e.printStackTrace()
                }
            }
        }
    }

    private fun convertToWav() {
        try {
            println("Converting MP3 to WAV...")
            val process = ProcessBuilder("ffmpeg", "-i", mp3FilePath, wavFilePath)
                .redirectErrorStream(true)
                .start()
            process.inputStream.bufferedReader().use { it.readText() }
            process.waitFor()
            println("Conversion completed: $wavFilePath")
        } catch (e: IOException) {
            println("Error converting file: ${e.message}")
            e.printStackTrace()
        }
    }

    fun stop() {
        clip?.stop()
        clip?.close()
        isPlaying = false
        println("Audio playback stopped")
    }
}

fun main() = application {
    var audioPlayer: AudioPlayer? = null

    program {
        extend {
            if (audioPlayer == null) {
                audioPlayer = AudioPlayer("C:\\videos\\godgangs\\godgangs.mp3")
                audioPlayer?.play()
            }
        }

        keyboard.keyDown.listen {
            if (it.name == "q") {
                audioPlayer?.stop()
                application.exit()
            }
        }
    }
}

```

It’s really simple and experimental but it can lead somewhere. Hope somebody finds it useful. Remember to replace the file paths!

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [October 4, 2024, 4:14pm UTC](https://openrndr.discourse.group/t/playing-a-simple-mp3-file/690/2 "2024-10-04T16:14:38Z")

</div>

> <https://github.com/openrndr/orx/blob/master/orx-jvm/orx-minim/src/demo/kotlin/DemoPlaySound01.kt>

🙂

If you find things which are missing or not well documented in the guide, I would be thankful for new issues at [Issues · openrndr/openrndr-guide · GitHub](https://github.com/openrndr/openrndr-guide/issues)

All your recent questions in the forum are very useful.

---

<div class="post-metadata">

**Author:** ![dedos](https://avatars.discourse-cdn.com/v4/letter/d/f07891/32.png) [@dedos](https://openrndr.discourse.group/u/dedos)\
**Post date:** [October 4, 2024, 4:18pm UTC](https://openrndr.discourse.group/t/playing-a-simple-mp3-file/690/3 "2024-10-04T16:18:14Z")

</div>

Well, I’m glad I’m not just being annoying then. I really like OPENRNDR and if I had a better head for coding I’d be glad to help more.

Thanks again! Happy to use minim and not a clunky workaround.

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [October 4, 2024, 4:19pm UTC](https://openrndr.discourse.group/t/playing-a-simple-mp3-file/690/4 "2024-10-04T16:19:53Z")

</div>

BTW. How did I find that example?

I didn’t remember how to play mp3, so I went into the orx folder and typed `ag mp3` in the terminal to find any mentions on all text files. `ag` is the [Silver Searcher](https://github.com/ggreer/the_silver_searcher).

There’s also `rg` ([RipGrep](https://github.com/BurntSushi/ripgrep)) which I discovered recently and claims to be faster.

---

<div class="post-metadata">

**Author:** ![dedos](https://avatars.discourse-cdn.com/v4/letter/d/f07891/32.png) [@dedos](https://openrndr.discourse.group/u/dedos)\
**Post date:** [October 4, 2024, 4:23pm UTC](https://openrndr.discourse.group/t/playing-a-simple-mp3-file/690/5 "2024-10-04T16:23:28Z")

</div>

Nice, I will keep this in mind and use Silver Searcher

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [October 4, 2024, 4:57pm UTC](https://openrndr.discourse.group/t/playing-a-simple-mp3-file/690/6 "2024-10-04T16:57:37Z")

</div>

I rarely use more arguments than these:

```auto
ag foo . --context 5 --width 100 --kotlin

```

Searches in `.` (current dir and subdirs), showing 5 lines above and below the hit, maxiumum 100 characters (I use this if there’s minimized javascript to avoid huge blobs of text in the results) and --kotlin is to only search that file type.

Also useful:

```auto
ag --list-file-types

```

🙂

---

<div class="post-metadata">

**Author:** ![dedos](https://avatars.discourse-cdn.com/v4/letter/d/f07891/32.png) [@dedos](https://openrndr.discourse.group/u/dedos)\
**Post date:** [October 4, 2024, 5:00pm UTC](https://openrndr.discourse.group/t/playing-a-simple-mp3-file/690/7 "2024-10-04T17:00:15Z")

</div>

Just so you know: the code you pasted above returns this:

```auto
Unresolved reference: minim

```

I have uncommented ` "orx-minim",` from the `gradle.build.kts` file, but it didn’t seem to resolve the issue. I have pasted the exact code from GitHub you have provided.

Is there anything else I’m missing?

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [October 4, 2024, 7:56pm UTC](https://openrndr.discourse.group/t/playing-a-simple-mp3-file/690/8 "2024-10-04T19:56:00Z")

</div>

Did you click the reload Gradle button after uncommenting the line?

---

<div class="post-metadata">

**Author:** ![dedos](https://avatars.discourse-cdn.com/v4/letter/d/f07891/32.png) [@dedos](https://openrndr.discourse.group/u/dedos)\
**Post date:** [October 4, 2024, 11:04pm UTC](https://openrndr.discourse.group/t/playing-a-simple-mp3-file/690/9 "2024-10-04T23:04:32Z")

</div>

no, I didn’t. sorry. it’s my 1st time using Gradle, Kotlin, IDEA etc. it works perfectly and I have already adapted it to my program. thanks a lot

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [October 7, 2024, 7:12am UTC](https://openrndr.discourse.group/t/playing-a-simple-mp3-file/690/10 "2024-10-07T07:12:43Z")

</div>

I added a [Usage section](https://github.com/openrndr/orx?tab=readme-ov-file#usage) to orx. Maybe it helps the next one 😄
