My MP3 player written in Swift (open source, GitHub link included)

Discussion in 'Mac Programming' started by maculateConception, Jun 27, 2017.

  1. maculateConception, Jun 27, 2017
    Last edited: Aug 17, 2017

    maculateConception macrumors regular

    maculateConception

    Joined:
    May 28, 2017
    Location:
    Die Bundesstaat Kalifornien
    #1
    Aural.png

    This project is on GitHub. https://github.com/maculateConception/aural-player

    Compatibility: Supports OS X 10.10 (Yosemite) or later. Older versions of OS X not supported (Sorry!)

    UPDATE (7/20/2017): Code ported to Swift v3. Swift 2 code is now in a separate branch.


    Hello, I wrote an MP3 player app for OS X, that I call "Aural". If you feel like trying it out, you'll find the latest source code and app bundle at the GitHub link above. I did this for fun and learning, and I also intended for it to be totally open source, so, if anyone is interested in dabbling with it, whether this is all new to you or you're an audiophile/pro and feel you could greatly improve it, please help yourself to the code.

    The app bundle comes with a complete PDF user guide, and on GitHub, you'll find the user guide + demo videos + a developer guide with some pointers into my code.

    NOTE - I'm new to Swift/OS X programming and this project is still in its early days, so note that it may have bugs. But, that's where the potential for fun lies. Programmers know what I mean ;)

    Any feedback/thoughts welcome ! I will try to post any updates here as they happen, but please check GitHub for the latest and greatest on this project.
     
  2. PatrickCocoa macrumors 6502a

    Joined:
    Dec 2, 2008
    #2
    Cool, thanks!
     
  3. maculateConception, Jun 28, 2017
    Last edited: Jun 30, 2017

    maculateConception thread starter macrumors regular

    maculateConception

    Joined:
    May 28, 2017
    Location:
    Die Bundesstaat Kalifornien
    #3
    I made some significant updates (and updated the attached files in my original post, accordingly):

    New feature: Now allows current playlist to be saved to a file and loaded
    Other feature update: All sliders now provide continuous feedback (as you slide them). Don't have to wait to release a slider for it to take effect.

    New look n feel !
    - Customized look and feel of all slider knobs (no more boring white circles)
    - Customized look and feel of pop up buttons and menus (EQ presets and reverb)

    Also, ...
    - Updated and better organized the user guide
    - Removed duplicate icon files from the ZIP archive posted here, cutting its size in half !
     
  4. maculateConception, Jul 1, 2017
    Last edited: Jul 1, 2017

    maculateConception thread starter macrumors regular

    maculateConception

    Joined:
    May 28, 2017
    Location:
    Die Bundesstaat Kalifornien
    #4
    Ok, I added a few more things (attached files updated accordingly):

    - Detailed track info: Upon clicking the "i" (more info) button in the top right corner, a popover appears, displaying detailed track information such as file name and size, format, bit rate, sample rate, album, genre, copyrights, etc.

    - Added a safety feature: A daemon task that keeps an eye on memory usage and kills the app if memory usage spikes up to an unsafe level

    - Added a horizontal line/bar across the center of all EQ sliders, for easy visual reference to the 0dB gain level

    - Fixed a few minor UI bugs
     
  5. maculateConception thread starter macrumors regular

    maculateConception

    Joined:
    May 28, 2017
    Location:
    Die Bundesstaat Kalifornien
    #5
    Major rewrite (ZIPs updated):

    - Fixed a serious memory leak issue caused by playing MP3 files with inaccurate duration metadata. Now works directly with audio buffers as opposed to using the scheduleFile/scheduleSegment APIs that can't play broken MP3s.
    - Implemented lazy loading (in stages) of track info, to significantly speed up app loading
    - Major code refactoring: Added a new third layer, a middleman/facade between the AppDelegate and Player, to greatly simplify both the player and AppDelegate.
     
  6. maculateConception thread starter macrumors regular

    maculateConception

    Joined:
    May 28, 2017
    Location:
    Die Bundesstaat Kalifornien
    #6
    A few more updates ...

    - Reorganized the effects controls into a tabbed group view with 3 items: EQ, Pitch Shift, and Reverb. Reverb and Pitch Shift panels display descriptions of the respective sound effects.
    - Added an EQ global gain / preamp control slider
    - Added a control slider for Reverb amount (wet/dry mix)
    - Added a control slider for Pitch overlap
    - Added 4 new Reverb presets
    - Modified the EQ slider knobs and other slider knobs' look n feel
     
  7. kage207 macrumors 6502a

    Joined:
    Jul 23, 2008
    #7
    Have you looked at using git to as your Version Control System (VCS)? There are ones out there like GitHub that you can host this on and people can pull down your code that way but also contribute back in an easier manner by submitting pull requests.
     
  8. maculateConception thread starter macrumors regular

    maculateConception

    Joined:
    May 28, 2017
    Location:
    Die Bundesstaat Kalifornien
    #8
    Hey, yes, absolutely. I've thought about hosting it on Github, but I'm just lazy about that, I guess :)

    But, now that you mention it, I will try to set it up there, instead.
     
  9. kage207 macrumors 6502a

    Joined:
    Jul 23, 2008
    #9
    Makes more sense too. You can provide a license and standards there. And start trying to build a community of developers to help you support it. :cool:
     
  10. maculateConception thread starter macrumors regular

    maculateConception

    Joined:
    May 28, 2017
    Location:
    Die Bundesstaat Kalifornien
    #10
    Done ! I've put the GitHub link in my original post up top. Thanks for getting me to actually do it :)
     
  11. viettanium macrumors regular

    Joined:
    Sep 3, 2010
    Location:
    Vietnam
  12. maculateConception, Jul 11, 2017
    Last edited: Jul 11, 2017
  13. maculateConception thread starter macrumors regular

    maculateConception

    Joined:
    May 28, 2017
    Location:
    Die Bundesstaat Kalifornien
    #13
    Added a time stretch feature to allow a change in playback rate

    Time.png
     
  14. abcdefg12345 macrumors regular

    abcdefg12345

    Joined:
    Jul 10, 2013
    #14
    This looks like a really nice player to use instead of vlc, can you update it for swift 3, i can't build it on Xcode 8.3.3
     
  15. maculateConception thread starter macrumors regular

    maculateConception

    Joined:
    May 28, 2017
    Location:
    Die Bundesstaat Kalifornien
    #15
    Thanks for the feedback.

    Unfortunately, I'm limited by my hardware (and hence my OS) ... I'm on a 2009 Macbook Pro running Yosemite (I can't do El Cap for app compatibility reasons), so I cannot go any higher than Swift v2.1.1. Sorry about that !

    I would love to be able to use Swift 3, trust me :(
     
  16. maculateConception thread starter macrumors regular

    maculateConception

    Joined:
    May 28, 2017
    Location:
    Die Bundesstaat Kalifornien
    #16
    Added new compact view options (ability to toggle playlist/effects views)

    Aural-playlistOnly.png

    Aural-effectsOnly.png

    Aural-compact.png
     
  17. maculateConception thread starter macrumors regular

    maculateConception

    Joined:
    May 28, 2017
    Location:
    Die Bundesstaat Kalifornien
    #17
    I'm currently working on adding a real-time visualization (vertical bars) ... made some progress, but don't have a firm grasp on it yet. I'm looking forward to the day when I'll have this ready ! It is quite involved !
     
  18. grahamwright1 macrumors regular

    Joined:
    Feb 10, 2008
    Location:
    North of the Border
    #18
    That sounds like a really interesting challenge - can you share some details on how you were able to analyze the real-time audio if / when you get it working?
     
  19. maculateConception thread starter macrumors regular

    maculateConception

    Joined:
    May 28, 2017
    Location:
    Die Bundesstaat Kalifornien
    #19
    Hey, yes, it is very interesting ... it is heavily mathematical in nature. The visualization process basically consists of the following high level steps:

    - Install a tap on the audio output line (in my case, an AVAudioEngine mixer node), to tap the data coming out
    - Set up a callback within the tap, so that your data analysis unit can be notified whenever new data is available (i.e. many times a second)
    - When new data is received, perform what's called a Fast Fourier Transform (FFT) ... Apple provides a framework to do this stuff (thank God for that !). This really does need to be fast, if you're doing real time analysis.
    - The FFT analysis converts time-based samples to frequency-based samples. In other words, the data you get out of FFT is in terms of frequency bands and the magnitude of sound at each such band.
    - Using the frequency/magnitude data, render some sort of visual representation. This could be simple vertical bars, one for each frequency band, or circles that dance to the beat, or some sort of funky particle emitter.

    The key, however, is efficiency. If the audio tap introduces a latency, or your computation/rendering are not able to keep up, there will be a definite lag in your visualization ... the view will look like me doing a salsa dance ... always a few steps behind.
     
  20. colinwil, Jul 18, 2017
    Last edited: Jul 18, 2017

    colinwil macrumors regular

    Joined:
    Nov 15, 2010
    Location:
    Reading, UK
    #20
    I updated it to Swift 3 and recompiled it with Xcode 8.3.3.

    It works!

    [​IMG]
     
  21. abcdefg12345 macrumors regular

    abcdefg12345

    Joined:
    Jul 10, 2013
    #21
    can you give some guidance how to update code to swift 3 i got some errors

    Code:
    self.underlyingQueue = DispatchQueue(label: queueName, attributes: [])
    
    Code:
    switch queueType {
            case .main: self.underlyingQueue = DispatchQueue.main
            case .global: self.underlyingQueue = DispatchQueue.global(priority: 0)
            case .custom: self.underlyingQueue = DispatchQueue(label: DispatchQueue.defaultCustomQueueName, attributes: [])
            }
    Code:
    for (freq,gain) in eqBands {
                eqBandsDict[String(freq)] = gain as NSNumber
            }
    Code:
    timer!.setTimer(start: DispatchTime.now(), interval: intervalNanos, leeway: intervalNanos / 10)
    Code:
    let objects = info.draggingPasteboard().readObjects(forClasses: [URL.classForArchiver()!], options: nil)
    Code:
    task_info(mach_task_self_,
                    task_flavor_t(TASK_BASIC_INFO),
                    task_info_t($0),
                    &count)
     
  22. colinwil macrumors regular

    Joined:
    Nov 15, 2010
    Location:
    Reading, UK
    #22
    The snag here is that the project has a class called DispatchQueue - which kind of clashes with the native Foundation's DispatchQueue
    One of the snags is that the project has a class called DispatchQueue - which can be confused with the regular Foundation DispatchQueue class. So you've got to be a bit careful.

    So for that bit, I did:

    Code:
    class DispatchQueue {
    
    
        var underlyingQueue: Dispatch.DispatchQueue!
    
        fileprivate static let defaultCustomQueueName: String = "Aural.queues.default"
    
    
        init(queueName: String) {
    
            // Assume custom queue
    
            self.underlyingQueue = Dispatch.DispatchQueue(label: queueName, attributes: [])
        }
    
    
        init(queueType: QueueType) {
    
            // Intended to be used for main or global queue, but if custom queue, use the default custom queue name
    
            switch queueType {
            case .main: self.underlyingQueue = Dispatch.DispatchQueue.main
            case .global: self.underlyingQueue = Dispatch.DispatchQueue.global(qos: DispatchQoS.QoSClass.userInteractive)
            case .custom: self.underlyingQueue = Dispatch.DispatchQueue(label: DispatchQueue.defaultCustomQueueName, attributes: [])
    
            }
        }
    }
    
    
    // GCD dispatch queue type
    
    enum QueueType {
        case main
        case global
        case custom
    }
    
    I'll put it on GitHub later...
    --- Post Merged, Jul 18, 2017 ---
    I've put it the Swift 3 version on Github at https://github.com/wilsoncpw/Aural

    I've added a note there that says...

    This is a Swift 3 port of the Aural MP3 player by 'maculateConception'. The original Swift 2 version can be found at:

    https://github.com/maculateConception/aural-player

    Please note that I only updated the project to Swift 3. All the design, development and hard work was done by the original developer
     
  23. maculateConception, Jul 19, 2017
    Last edited: Jul 19, 2017

    maculateConception thread starter macrumors regular

    maculateConception

    Joined:
    May 28, 2017
    Location:
    Die Bundesstaat Kalifornien
    #23
    Hi colinwill, thanks so much for doing this ! I really appreciate your time and effort. This is going to be very valuable for all devs wanting to mess with it. My Swift 2 version is not very practical for those wanting to be on the cutting edge.

    Are you "codebreede" on GitHub ? Did you send me a pull request to update the main branch with your Swift 3 version ?

    I wanted to send you a private message on GitHub but they don't allow private messaging. I'm glad I found you here.

    In any case, I was going to reply saying that I'd appreciate it if you could keep the Swift 3 version in a separate fork/branch/repo/whatever, because I am unable to develop with Swift v3 (my OS and hardware are outdated). So, I will continue to use/update the Swift 2 repo.

    If you want, I can create a fork under my repo, and add you as a contributor. That way, both versions are in one place, and easier for folks to find. And, you can keep working on the Swift 3 version there. Let me know what works for you.

    Keep up the good work ! Cheers !

    BTW, I've made quite a few updates since you forked my repo. If you want the latest, you'll need another merge.
     
  24. colinwil macrumors regular

    Joined:
    Nov 15, 2010
    Location:
    Reading, UK
    #24
    Hi,

    No - I'm wilsoncpw on github. I've got several repos there - most of them are throw-away things I've been experimenting on, though a couple of them - Image Viewer 4 and CWSocketsEx are starting to look quite promising :)

    Yes - I think that would be the best. For a start, my Github skills are pretty basic. If you create a Swift 3 fork in your repo I'll re-publish it there
     
  25. maculateConception thread starter macrumors regular

    maculateConception

    Joined:
    May 28, 2017
    Location:
    Die Bundesstaat Kalifornien
    #25
    Actually, here's a surprising development. I'm thinking of upgrading to MacOS Sierra (using the hack), so if that succeeds, I'll start developing with Swift 3 myself. If it doesn't, and I'm stuck with Swift 2, I'll create that fork under my repo.

    I'll keep you posted on what happens.
     

Share This Page