shirakumo / harmony Goto Github PK
View Code? Open in Web Editor NEWA Common Lisp sound system
Home Page: https://shirakumo.github.io/harmony
License: zlib License
A Common Lisp sound system
Home Page: https://shirakumo.github.io/harmony
License: zlib License
## About Harmony Harmony is a library that provides you with audio processing tools as well as an audio server to play back music, sfx, and so forth. It is most suited for use in a game engine, but may feasibly also used for more advanced things such as a DAW. ## Quick Start To get running with a usable setup in no time flat, simply load harmony, an appropriate drain extension from cl-mixed, and some extension to play a file: :: common lisp (ql:quickload '(harmony cl-mixed-mpg123 #+android cl-mixed-aaudio #+linux cl-mixed-pulse #+darwin cl-mixed-coreaudio #+windows cl-mixed-wasapi #+bsd cl-mixed-oss)) :: Then start a server: :: common lisp (org.shirakumo.fraf.harmony:maybe-start-simple-server) :: And we can play some stuff back: :: common lisp (org.shirakumo.fraf.harmony:play #p"~/my-music.mp3" :mixer :music) :: The returned ``voice`` instance can be controlled with functions like ``stop`` and ``mixed:volume``. Please see the documentation of the ``voice`` class for more hints on possible interactions. For one more quick illustration of Harmony's capabilities, let's restart the playback, but now with a lowpass filter applied: :: common lisp (org.shirakumo.fraf.harmony:stop *) (org.shirakumo.fraf.harmony:play #p"~/my-music.mp3" :mixer :music :effects '((mixed:biquad-filter :filter :lowpass :frequency 400))) :: There's a lot more that can be done, such as chaining multiple filters, controlling the amount of mixers, applying effects to entire mixers, looping playback, horizontal mixing, and more. The default ``play`` method as shown above will always allocate the necessary objects once called, and free them once playback is finished. This can involve disk access and other slow operations. If you need your playback to occur with as little delay as possible, you should instead first use ``create`` to allocate your voice with the appropriate settings, and then ``play`` once desired. When initialised, via ``create``, the same voice can also be re-played multiple times, but must be manually ``free``d once no longer needed. ## Environments Environments are a way to handle music environments and horizontal mixing. To define a horizontal mixing environment, simply create an ``environment`` instance, passing the desired environment sets as ``:sets``: :: common lisp (make-instance 'org.shirakumo.fraf.harmony:environment :sets '((:normal #p"normal-track.mp3" #p"normal-track-calm") (:intense #p"intense-track.mp3"))) :: This defines an environment with two sets, ``:normal`` and ``:intense``. When the normal set is playing, it will loop through ``normal-track`` and ``normal-track-calm``. When the intense set is playing, it will loop through ``intense-track``. You can activate a set by using ``transition``: :: common lisp (org.shirakumo.fraf.harmony:transition * :normal) (org.shirakumo.fraf.harmony:transition ** :intense :in 10.0) :: If you'd like more fine-grained control over the segments that are being played back, you can also manually construct ``music-segment`` instances and use the ``transition`` function to fade between ``music-segment``s or change their volumes. ## Also See - "cl-mixed"(https://shirakumo.github.io/cl-mixed) For the mixing and sound processing library.
(ql:quickload :harmony-simple)
(harmony-simple:initialize)
(defvar *explosion* (harmony-simple:decode #p"kick.mp3"))
(harmony-simple:play 'harmony:buffer-source :sfx :buffers *explosion*)
* debugger invoked on a SB-INT:INVALID-ARRAY-INDEX-ERROR in thread
#<THREAD "#<DEFAULT-SERVER running> process thread." RUNNING {1003D2C393}>:
Invalid index 1 for (SIMPLE-VECTOR
1), should be a non-negative integer below 1.
It does work in the following combinations:
This is probably a bug in libmixed somewhere, but drain resampling to match output spec results in real bad noise.
Yeah, I'm sure this is probably a mess. When I use Harmony with my laptop speakers/headphone jack it works fine. If I try to use my monitor's speakers (over USB) I get:
[SBCL] CL-USER> (harmony-simple:start)
debugger invoked on a DIVISION-BY-ZERO in thread
#<THREAD "main thread" RUNNING {1001936D83}>:
arithmetic error DIVISION-BY-ZERO signalled
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
("bogus stack frame")
It looks like fades are set up to occur at the beginning of a segment via time. If you wanted had, say, a 60 second clip and you wanted to fade from 0.0 up to 1.0 over the first 5 seconds, then fade from 1.0 down to 0.0 in the last 5 seconds, how would you accomplish it? And is there any way to do this if you don't know the length of the clip in advance?
Thanks.
For BSDs and other simpler system where ALSA and PulseAudio don't exist, adding an OSS drain would be nice.
Gday,
First time user, relatively new lisper.
I have quicklisp setup, i have it searching and installing.
I'm following instructions from https://shirakumo.github.io/harmony/ , and i cant install harmony-simple
I am using sbcl with todays quicklisp.
I run:
(ql:quickload :harmony-simple)
System "harmony-simple" not found
[Condition of type QUICKLISP-CLIENT:SYSTEM-NOT-FOUND]
This doc mentions that its version 2.0.0
Harony system says its version 2.0.0
(asdf:defsystem harmony
:version "2.0.0"
Am I doing something wrong ?
Thanks.
Thanks so much this library. I was having trouble with 2 second latencies with a different OpenAL bindings library and this one performs much better.
playing ogg files works but playing too many at once crashes easily.
Sample code:
(dotimes (x 20) (org.shirakumo.fraf.harmony:play #P"file.ogg"))
is giving me
Unhandled memory fault at #x7FC862C042F0. [Condition of type SB-SYS:MEMORY-FAULT-ERROR]
it doesn't bother me though cause i don't get this problem converting to MP3 but i thought i'd just point it out in case anyone else is trying this library.
My current workflow is
decode
a file into a buffer.play
it with :paused t
to get the buffer-sourceresume
the buffer-source when i want to play itcan I change the volume on each reproduction like this? tried and failed using the volume accessor and the :volume parameter but an example would help
(harmony-simple:initialize :output-spec '(harmony-openal:openal-drain))
, though I was able to start the other backends. I think i need this one for 3d audio and pitch shifting.From the error below i compared the code to other initialize-packed-audio drains but looks the same code, not sure what is missing:
There is no applicable method for the generic function
#<STANDARD-GENERIC-FUNCTION HARMONY:BUFFERSIZE (1)>
when called with arguments
(#.(SB-SYS:INT-SAP #X00FA56B0)).
[Condition of type SB-PCL::NO-APPLICABLE-METHOD-ERROR]
See also:
Common Lisp Hyperspec, 7.6.6 [:section]
Restarts:
0: [RETRY] Retry calling the generic function.
1: [RETRY] Retry SLIME REPL evaluation request.
2: [*PROCESS-INPUT] Continue reading input.
3: [ABORT] Return to SLIME's top level.
4: [CLOSE-CONNECTION] Close SLIME connection.
5: [ABORT] Exit debugger, returning to top level.
Backtrace:
0: ((:METHOD NO-APPLICABLE-METHOD (T)) #<STANDARD-GENERIC-FUNCTION HARMONY:BUFFERSIZE (1)> #.(SB-SYS:INT-SAP #X00FA56B0)) [fast-method]
1: (SB-PCL::CALL-NO-APPLICABLE-METHOD #<STANDARD-GENERIC-FUNCTION HARMONY:BUFFERSIZE (1)> (#.(SB-SYS:INT-SAP #X00FA56B0)))
2: ((:METHOD HARMONY:INITIALIZE-PACKED-AUDIO (HARMONY-OPENAL:OPENAL-DRAIN)) #<HARMONY-OPENAL:OPENAL-DRAIN >) [fast-method]
Locals:
HARMONY:DRAIN = #<HARMONY-OPENAL:OPENAL-DRAIN >
3: ((:METHOD INITIALIZE-INSTANCE (HARMONY:PACK-DRAIN)) #<HARMONY-OPENAL:OPENAL-DRAIN > :CONTEXT #<HARMONY-SIMPLE:DEFAULT-SERVER > :NAME NIL) [fast-method]
Locals:
SB-PCL::.NEXT-METHOD-CALL. = #S(SB-PCL::FAST-METHOD-CALL ..)
SB-PCL::.REST-ARG. = (:CONTEXT #<HARMONY-SIMPLE:DEFAULT-SERVER > :NAME NIL)
HARMONY:DRAIN = #<HARMONY-OPENAL:OPENAL-DRAIN >
4: ((SB-PCL::EMF INITIALIZE-INSTANCE) #<unused argument> #<unused argument> #<HARMONY-OPENAL:OPENAL-DRAIN > :CONTEXT #<HARMONY-SIMPLE:DEFAULT-SERVER > :NAME NIL)
5: ((:METHOD INITIALIZE-INSTANCE :AROUND (CL-MIXED:C-OBJECT)) #<HARMONY-OPENAL:OPENAL-DRAIN > :CONTEXT #<HARMONY-SIMPLE:DEFAULT-SERVER > :NAME NIL) [fast-method]
Locals:
SB-PCL::.NEXT-METHOD-CALL. = #S(SB-PCL::FAST-METHOD-CALL :FUNCTION #<CLOSURE (SB-PCL::COMBINED-METHOD INITIALIZE-INSTANCE) {10078F12EB}> :PV NIL :NEXT-METHOD-CALL NIL :ARG-INFO (1 . T))
SB-PCL::.REST-ARG. = (:CONTEXT #<HARMONY-SIMPLE:DEFAULT-SERVER > :NAME NIL)
CL-MIXED::OBJECT = #<HARMONY-OPENAL:OPENAL-DRAIN >
6: ((:METHOD MAKE-INSTANCE (CLASS)) #<STANDARD-CLASS HARMONY-OPENAL:OPENAL-DRAIN> :CONTEXT #<HARMONY-SIMPLE:DEFAULT-SERVER > :NAME NIL) [fast-method]
7: ((:METHOD HARMONY-SIMPLE:MAKE-PIPELINE (HARMONY-SIMPLE:DEFAULT-SERVER)) #<HARMONY-SIMPLE:DEFAULT-SERVER >) [fast-method]
Locals:
HARMONY:PIPELINE = #<HARMONY:PIPELINE 0 nodes>
HARMONY:SERVER = #<HARMONY-SIMPLE:DEFAULT-SERVER >
8: ((:METHOD INITIALIZE-INSTANCE :AFTER (HARMONY-SIMPLE:DEFAULT-SERVER)) #<HARMONY-SIMPLE:DEFAULT-SERVER >) [fast-method]
Locals:
HARMONY:SERVER = #<HARMONY-SIMPLE:DEFAULT-SERVER >
9: ((SB-PCL::EMF INITIALIZE-INSTANCE) #<unused argument> #<unused argument> #<HARMONY-SIMPLE:DEFAULT-SERVER > :OUTPUT-SPEC (HARMONY-OPENAL:OPENAL-DRAIN) :BUFFERSIZE 441 :SAMPLERATE 44100)
10: ((:METHOD MAKE-INSTANCE (CLASS)) #<STANDARD-CLASS HARMONY-SIMPLE:DEFAULT-SERVER> :OUTPUT-SPEC (HARMONY-OPENAL:OPENAL-DRAIN) :BUFFERSIZE 441 :SAMPLERATE 44100) [fast-method]
11: (HARMONY-SIMPLE:INITIALIZE :OUTPUT-SPEC (HARMONY-OPENAL:OPENAL-DRAIN))
Locals:
SB-DEBUG::MORE = (:OUTPUT-SPEC (HARMONY-OPENAL:OPENAL-DRAIN))
12: (SB-INT:SIMPLE-EVAL-IN-LEXENV (INIT-AUDIO) #<NULL-LEXENV>)
13: (EVAL (INIT-AUDIO))
on the preview video https://www.youtube.com/watch?v=rMXLgQEXS8g you could access the location of a mp3 source, but that seems missing on the current code.
I could still get the location of the :sfx mixer though.
> (defvar *tmp* (harmony-simple:play #p"/home/user/421128__giocosound__footstep-grass-4.mp3" :sfx :paused t))
#<HARMONY-MP3:MP3-SOURCE paused>
> (harmony-simple:location *tmp*)
There is another way to do it atm?
Cool library. Looks like right now, it only supports mp3 through cl-mpg123.
Hello.
I am getting a random crash playing a few sound files as MP3s in harmony. Stack trace mentions cl-mixed.
tested with latest versions:
harmony commit [cc92624]
mixed commit [72cfd9b]
rough steps:
(ql:quickload :harmony)
(org.shirakumo.fraf.harmony:start (org.shirakumo.fraf.harmony:make-simple-server))
(org.shirakumo.fraf.harmony:play #p"some-file.mp3") ...
if i missed something please let me know
Stack trace (visible only in the sly-inferior-lisp for sbcl buffer):
WARNING:
redefining EMACS-INSPECT (#<SB-PCL:SYSTEM-CLASS COMMON-LISP:T>) in DEFMETHOD
;; Slynk started at port: 40987.
SLYNK's ASDF loader finished.
40987
fatal error encountered in SBCL pid 886899 tid 889757:
STOP_FOR_GC_PENDING, but why?
0: fp=0x7fa97d28da70 pc=0x55c51eb99834 Foreign function (null)
1: fp=0x7fa97d28da80 pc=0x55c51eb9984a Foreign function (null)
2: fp=0x7fa97d28db70 pc=0x55c51eb99a21 Foreign function (null)
3: fp=0x7fa97d28dc70 pc=0x55c51eb9b332 Foreign function (null)
4: fp=0x7fa97d28e240 pc=0x7fa97f191520 Foreign function (null)
5: fp=0x7fa97d28e270 pc=0x52a4b8a0 SB-EVAL::%EVAL
6: fp=0x7fa97d28e2d8 pc=0x52c9ad81 SB-EVAL::EVAL-LET
7: fp=0x7fa97d28e308 pc=0x52b2a342 (SETF SB-ALIEN-INTERNALS::%ALIEN-VALUE)
8: fp=0x7fa97d28e388 pc=0x53bfc55e (LAMBDA (SB-ALIEN::ARGS-POINTER SB-ALIEN::RESULT-POINTER FUNCTION) :IN "/path/to/cl-mixed/segments/virtual.lisp")
9: fp=0x7fa97d28e3c0 pc=0x55c51ebc09b6 Foreign function funcall_alien_callback
10: fp=0x7fa97d28e3d0 pc=0x501003d2 (unknown lisp object)
11: fp=0x7fa97d28e420 pc=0x50001640 Foreign function
12: fp=0x7fa97d28e460 pc=0x7fa97ca0657b Foreign function (null)
13: fp=0x7fa97d28e480 pc=0x7fa97c9fe5e8 Foreign function mixed_segment_mix
14: fp=0x7fa97d28e4b8 pc=0x545471b6 (LAMBDA (FUN1194 G1195))
15: fp=0x7fa97d28e4e0 pc=0x53b93bc8 ORG.SHIRAKUMO.FRAF.MIXED.CFFI::SEGMENT-MIX
16: fp=0x7fa97d28e680 pc=0x53c22714 (SB-PCL::FAST-METHOD ORG.SHIRAKUMO.FRAF.HARMONY::RUN (ORG.SHIRAKUMO.FRAF.HARMONY::SERVER))
17: fp=0x7fa97d28e7a0 pc=0x53c1ee93 (LAMBDA () :IN ORG.SHIRAKUMO.FRAF.MIXED::START)
18: fp=0x7fa97d28e8a0 pc=0x536914d0 (LAMBDA () :IN BORDEAUX-THREADS::BINDING-DEFAULT-SPECIALS)
19: fp=0x7fa97d28e990 pc=0x52bac659 (FLET SB-UNIX::BODY :IN SB-THREAD::RUN)
20: fp=0x7fa97d28ea80 pc=0x52bace09 (FLET "WITHOUT-INTERRUPTS-BODY-10" :IN SB-THREAD::RUN)
21: fp=0x7fa97d28ebd8 pc=0x52bac33b (FLET SB-UNIX::BODY :IN SB-THREAD::RUN)
22: fp=0x7fa97d28ecc8 pc=0x52bac038 (FLET "WITHOUT-INTERRUPTS-BODY-3" :IN SB-THREAD::RUN)
23: fp=0x7fa97d28edb8 pc=0x52babeeb SB-THREAD::RUN
24: fp=0x7fa97d28edf0 pc=0x55c51ebc096a Foreign function call_into_lisp
25: fp=0x7fa97d28ee10 pc=0x55c51eb9199d Foreign function funcall1
It seems that quicklisp can't find the system, is there an alternative way to install?
Applying mixer:pitch
effect results in loud noise instead of actual sample.
(harmony:play #p"sample.wav" :effects '((mixer:pitch :pitch 1.5))) ; or any other pitch except for 1.0
;; Doesn't work for other formats as well, for example .mp3
On a side note, it would be nice if it was possible to do (mixer:make-pitch :pitch 1)
, i.e. pass non single-floats as arguments.
I get this: Unhandled PACKAGE-DOES-NOT-EXIST in thread #<SB-THREAD:THREAD "main thread" RUNNING {10008E8083}>: The name "CL-MIXED" does not designate any package.
Log here: http://report.quicklisp.org/2020-09-02/failure-report/harmony.html#harmony
This happens on Windows and supposedly OS X
Just cloned the project and was walking through your readme to understand it better. Looks like you originally initialized your server with harmony-simple:initialize but maybe changed the name to start? Initialize no longer seems to exist and start does work.
not sure if it is unsupported, a bug or something that could potentially be done with a custom segment (which I haven't read yet)
given 3 stereo mp3-sources when I resume/play them on :music they work fine individually but once I resume a 2nd or 3rd one the audio of the "old" one outputs only on 1 channel and the "new" one is hear on both channels
and as i remove (stop looping) sources 1 always gets stereo and the other 1 channel output
After (harmony-simple:initialize)
is done i try to play a short wav (harmony-simple:play #p"/home/user/421128__giocosound__footstep-grass-4.wav" :sfx)
and i get a heap error. Everything works fine if I use .mp3 so is not a stopper for me.
On *inferior-lisp*
Heap exhausted during garbage collection: 0 bytes available, 16 requested.
Gen Boxed Unboxed LgBox LgUnbox Pin Alloc Waste Trig WP GCs Mem-age
0 0 0 0 0 0 0 0 10737418 0 0 0.0000
1 7401 2463 0 0 6 322805904 417648 10737418 9864 0 1.0000
2 10423 3467 0 0 23 454734752 412768 10737418 13890 0 0.0000
3 1329 539 82 75 127 63531888 2823312 2000000 2025 0 0.0000
4 0 0 0 0 0 0 0 2000000 0 0 0.0000
5 0 0 0 0 0 0 0 2000000 0 0 0.0000
6 441 220 64 47 0 24496608 800288 2000000 772 0 0.0000
7 6217 0 0 0 0 203718656 0 2000000 6217 0 0.0000
Total bytes allocated = 1069287808
Dynamic-space-size bytes = 1073741824
GC control variables:
*GC-INHIBIT* = true
*GC-PENDING* = true
*STOP-FOR-GC-PENDING* = false
fatal error encountered in SBCL pid 23889(tid 0x7f7fe5397040):
Heap exhausted, game over.
Error opening /dev/tty: No such device or address
Welcome to LDB, a low-level debugger for the Lisp runtime environment.
This is SBCL 1.4.5.3-cd28228, an implementation of ANSI Common Lisp.
More information about SBCL is available at http://www.sbcl.org/.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
#<SB-THREAD:THREAD "# process thread." RUNNING {10030E59B3}>
debugger invoked on a SB-KERNEL:NO-NATIVE-NAMESTRING-ERROR in thread
#<THREAD "main thread" RUNNING {10005E85B3}>:
The pathname
#P"/home/imac/Music/Louis The Child ft. K.Flay - It's Strange [Premiere] (FIFA 16 Soundtrack) - 128kbps.mp3"
does not have a native namestring because
of the :NAME component #<SB-IMPL::PATTERN "Louis The Child ft. K.Flay - It's Strange "
(:CHARACTER-SET . "Premiere")
" (FIFA 16 Soundtrack) - 128kbps">.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(SB-KERNEL:NO-NATIVE-NAMESTRING-ERROR #P"/home/imac/Music/Louis The Child ft. K.Flay - It's Strange [Premiere] (FIFA 16 Soundtrack) - 128kbps.mp3" "of the ~S component ~S." :NAME #<SB-IMPL::PATTERN ("Louis The Child ft. K.Flay - It's Strange " (:CHARACTER-SET . "Premiere") " (FIFA 16 Soundtrack) - 128kbps")>)
0] 0
#<HARMONY-MP3:MP3-SOURCE playing>
debugger invoked on a SB-SYS:MEMORY-FAULT-ERROR in thread
#<THREAD "# process thread." RUNNING {10030E59B3}>:
Unhandled memory fault at #x0.
Currently, since there is no association between sources and their mixers, a source will remain on the mixer even if it has ended and it is technically not allowed to play it. It would be much more intuitive and useful if there was a mechanism to automatically remove the source from the mixer.
It would be nice to allow native Jack integration for systems that use it.
When pausing track that is being played, sometimes it's replaying over and over the last played sound. Im on Windows 10.
it might not be clearing a buffer right on pause. ~ Shinmera
Code to reproduce:
(defparameter *temp* nil)
(ql:quickload :harmony-simple)
(harmony-simple:initialize )
(setf *temp*
(harmony-simple:play #p"banks.mp3" :music))
(harmony-simple:pause *temp*)
(harmony:resume *temp*)
(harmony-simple:pause *temp*)
(harmony:resume *temp*) ;; etc
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.