:point_up: I think this is off topic and should probably be removed - but I haven’t as I don’t have particularly strong feelings. My strongest feeling is this is a bit weak and the community can do better. On this basis there will be a ‘best meme’ category in the summer picture competition.
(You still have to annotate your meme programmatically using a racket language - no mspaint or photoshop)
I don’t think I get it. Is this image a reference to something in particular? :confused:
Maybe the god xkcd thing that actually is funny https://xkcd.com/224/\|https://xkcd.com/224/
@lgt.twinslash has joined the channel
@tim986 Probably too late, but just found: https://docs.racket-lang.org/overscan/index.html?q=audio
ooh… not too late… (probably not going to be used this time round)… but that looks cool.
@advait.raykar has joined the channel
Need some help here, super new to Racket. https://stackoverflow.com/questions/62391543/how-play-mp3-audio-files-in-racket Don’t know best approach
You can use rsound
to play wav
files. Don’t know how to play mp3’s directly.
I see, but I don’t think it allows me to pause, and play as far as I can see. I am surprised that there are libraries for this, but not for mp3. This seems like a very obscure/neglected use case for racket I stumbled upon. Or maybe I am to inexperienced in audio stuff
Maybe @jbclements know more?
Maybe there is support for sound in the bindings for SDL? https://github.com/cosmez/racket-sdl
Saw the repo, this looks so confusing. Doesn’t look beginner friendly at all. I think it feels like a bit off way more than I can chew.https://docs.racket-lang.org/libopenal-racket/index.html Even the basic OGG example in this doc doesn’t work for me.
../../../Applications/Racket v7.7/collects/ffi/unsafe.rkt:131:0: ffi-lib: couldn't open "libvorbisfile.dylib" (dlopen(libvorbisfile.dylib, 6): image not found)
is what I get, another error I can’t figure how to trouble shoot at all.
Which OS are you on? macOS?
Yeah
The error says “libvorbisfile.dylib” is missing. That means we need to install Vorbis first.
libopenal-racket doesn’t distribute the shared libraries (don’t know why)
I did a brew install libvorbis, but that didn’t help.
Is Vorbis different? Will I have to build from source or something?
No, it just means that libvorbis needs to be placed in the shared library search path used by Racket.
Let’s see - there is a command that shows where Racket looks.
In the mean time, try: mdfind libvorbis in the terminal to see where brew installed your copy.
Yep
Type: (get-lib-search-dirs)
in Racket (or DrRacket) to see the search path.
/Users/advait/Downloads/libvorbisfile.3.dylib
/Users/advait/Racket/#sounds.rkt#1#
/Users/advait/Racket/sounds.rkt
/Users/advait/Library/Racket/planet/300/7.7/cache/gcr/libvorbisfile.plt
/Users/advait/Library/Racket/planet/300/packages/gcr/libvorbisfile.plt/1/6/libvorbisfile.plt
/Users/advait/Library/Racket/planet/300/packages/gcr/libvorbisfile.plt
/usr/local/Cellar/libvorbis/1.3.6/lib/libvorbisfile.3.dylib
/usr/local/Cellar/libvorbis/1.3.6/lib/libvorbis.0.dylib
/usr/local/Cellar/libvorbis/1.3.6/lib/libvorbisenc.2.dylib
/usr/local/Cellar/libvorbis
/usr/local/Cellar/libvorbis/1.3.6/share/doc/libvorbis-1.3.6
/usr/local/Cellar/libvorbis/1.3.6/share/doc/libvorbis-1.3.6/libvorbis
/usr/local/Cellar/libvorbis/1.3.6/lib/libvorbis.a
/usr/local/Cellar/libvorbis/1.3.6/lib/libvorbisenc.a
/usr/local/Cellar/libvorbis/1.3.6/lib/libvorbisfile.a
/usr/local/var/homebrew/locks/libvorbis.formula.lock
/usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/libvorbis.rb
Will try the other command in DrRacket
First do (require setup/dirs)
then Type: (get-lib-search-dirs)
Okay, got it where it is looking (#<path:/Users/advait/Library/Racket/7.7/lib>
#<path:/Applications/Racket v7.7/lib>)
Does play-sound
from racket/gui/base
work in this case?
Oh! Forgot about play-sound
. It doesn’t pop up when searching for “mp3” nor “audio”.
Where can I find the docs for this? All I can find is #lang racket/gui
(play-sound "some-sound.wav" #f)
This snippet from rosetta code.
Use http://docs.racket-lang.org\|docs.racket-lang.org to find (almost) everything.
This maybe exactly what I need. Thank you so much, is honestly so nice of you to help a random stranger on the internet, especially someone like me who is new to the language! Thanks @mflatt for this suggestion.
You are welcome.
Well, I realise that this works great for playing sounds, but I don’t think I have the ability to pause or scrub a track. I will prob look at the source for this to find out how I can do this.
If you’re interested in doing things like pausing and scrubbing (playing backwards/forwards, ideally while varying the rate for that “rocking the tape wheel” effect) I think rsound
is the closest thing Racket has.
But it might be more low-level than you want (i.e. more work including audio DSP stuff than you’re prepared to do, for e.g. “scrubbing”).
For play/pause, I think the missing piece is an MP3 decoder — take an MP3 file and decode it to raw wave that rsound
understands.
If you don’t mind a little latency, you could decode the whole file to a .wav file up front, then read that into rsound.
Maybe using some existing command-line converter.
I think the onerous MP3 patent finally expired (?) so there may be more choices here these days, then when I did a lot of this stuff.
(More choices and fewer patent trolls trying to suck your blood. :smile:)
@advait.raykar ^ more info than you probably want/need
For a long time I was blissfully unaware that sound was difficult. Especially if you need both low latency and portability at the same time.
Not a cakewalk at all :wink:
Well, the more the info, the better. I think I will sacrifice the latency for the ability to scrub. If it comes to it, I will prob get down and dirty with the dsp stuff. I am exploring RSound now, will do the conversion to wav
for now. Thanks @greg
Cool. And actually scrubbing is just varying the playback rate — letting the speed and frequency both change. The harder DSP stuff is changing one without the other, and making it sound good. :wink: As you probably already know. Good luck!
Well, I don’t know that much about dsp, but I know I really want to make this happen. Thanks for this!
@oliverfencott has joined the channel
@mflatt I have now presented the talk I was working on, so I am now looking into submitting PRs for my more involved drawing changes. :slightly_smiling_face: One such change I made is the addition of push-group
and draw-group
methods to dc<%>
, which correspond to cairo_push_group
and cairo_pop_group_to_source
+ cairo_paint_with_alpha
internally. This makes it possible to define a version of cellophane
that blends the entire pict uniformly, rather than applying the opacity to each drawing operation individually (which I find is essentially never what I want).
However, one impedance mismatch between these operations and Racket’s dc<%>
API is that cairo_push_group
calls cairo_save
internally, and cairo_pop_group_to_source
correspondingly calls cairo_restore
. This makes sense, and is in fact quite useful, but dc<%>
maintains its own internal state, which would not be saved/restored and therefore could go out of sync with the Cairo state.
Do you think it makes sense to add support for cairo_save
and cairo_restore
as part of this change, with methods of dc<%>
that properly handle saving and restoring the internal state? Or is there some reason that is not desirable and/or likely to be difficult given the way things are currently implemented? Another option could be to have a different API that accepts a record-dc%
and composites the entire thing all at once, keeping the stateful Cairo API an implementation detail. Do you have any preference?
Also, rather than using record-dc%
, another option would be to have an API that produces a new dc<%>
with the same state as the current one, but backed by a Cairo recording surface. That might be more useful here than using Racket’s own record-dc%
.
Looks like you folks covered all the bases on rsound. It sounds like the “right” interface for this would be something that plays a file from start to finish but also allows you to asynchronously alter the playback point.
Actually, you know what? I hate it when important information gets stuck in Slack (and then deleted), so I think I’m just going to respond to this thread in an email to racket users.
I like the ideas that avoid matching push-group
and draw-group
externally, and that last idea of producing a new dc<%>
sounds especially nice.
@advait.raykar Are you on the mailing list?
Alright, I will look into that approach. Thanks!
Ooh, good point. I’m happy to forward my message to an e-mail address you supply. Or even paste it here?
@lexi.lambda For a record-dc% backed by Cairo, see: https://github.com/soegaard/metapict/blob/master/metapict/crop.rkt#L50
I used it get acces to get-inked-extents
.
Oh, thanks. I’d been thinking about what the right API might look like. The approach I’d been converging on was to do something like this: 1. Add a new layer%
class which is like bitmap%
but uses a recording surface. 2. Add a new layer-dc%
class that draws into a layer%
the same way a bitmap-dc%
draws into a bitmap%
. 3. Add a draw-layer
method to dc<%>
. 4. Allow a layer%
to be used as a brush/pen stipple in addition to a bitmap%
. Basically, this would be mirroring the existing approach for bitmap%
for consistency. I don’t know if that’s actually a good idea or not, though—maybe the bitmap%
API should not be emulated? I imagine it’s rather old.
A different approach would be to merge layer%
and layer-dc%
into a single concept, like recording-dc%
. @mflatt, I don’t mean to bother you about API bikeshedding, but I imagine you have more of an informed opinion about this than I do.
Another option would to just not bother with having a separate concept and instead reuse recording-dc%
. It’s a bit awkward: there’s quite a lot of conceptual overlap here, but recording-dc%
is designed to be serializable, while this hypothetical layer%
concept is designed to be used as a Cairo drawing source.
So a layer
plays the same role cairo_pattern_t
does?
I imagined layer%
and layer-dc%
combined into a single concept and tied to a particular dc<%>
instance (i.e., the layer can only be drawn to the dc<%>
that created it), but I didn’t think about it much. I wouldn’t try to make it allowed as a stipple, because then you have to consider more interactions, like the target shape for brush drawing plus the current clipping region.
> i.e., the layer can only be drawn to the dc<%>
that created it I was originally imagining something like that, too, but the implementation strategy I had in mind was to just create a new Cairo surface, in which case the restriction would be totally arbitrary. I guess a different approach would be an API that “locks” the dc<%>
while the layer is being drawn, so it could use cairo_push_group
internally, but that seems like it would be awkward to use.
> I wouldn’t try to make it allowed as a stipple, because then you have to consider more interactions, like the target shape for brush drawing plus the current clipping region. Alright, that’s fine—I don’t actually know much about how stipples work, and I was just thinking about doing that because it seemed like a natural extension of the API. But if it’s difficult, I’m happy to not do it. :slightly_smiling_face:
If I remember correctly, a record-dc%
isn’t backed by a Cairo surface. So, pinning a layer to a dc<%>
instance (or at least class) gives you the option of implementing it with a Cairo surface when applicable, while that’s no so straightforward without pinning. Meanwhile, I agree that locking a dc<%>
isn’t an attractive API.
> So, pinning a layer to a dc<%>
instance (or at least class) gives you the option of implementing it with a Cairo surface when applicable @mflatt I’m not sure I understand—can’t you draw the same Cairo surface into any dc<%>
?
Not to a record-dc%
, unless I misremember.
Ah, I see your point—you would need the layer to do the recording record-dc%
does and be a Cairo surface. That makes sense, thanks.
I guess technically it’s possible to serialize a Cairo surface using <https://www.cairographics.org/manual/cairo-Script-Surfaces.html|script surfaces>. But those require 1.12, and I’m not sure how common/uncommon it is to have a Cairo installation compiled with that enabled.
@raykar.ath has joined the channel
I’m confused about the format of compile-omit-paths
. There’s a directory at rosette/lib/trace/report/node_modules
which I don’t want raco setup
to go into. I tried (list "node_modules")
, (list "rosette/lib/trace/report/node_modules")
, (list "rosette/rosette/lib/trace/report/node_modules")
. None of these works. What’s the right way?
Ah, apparently compile-omit-paths
doesn’t work with multi collection packages.
No, I am not on in the mailing list, I will hop on it.
I am also trying to figure out sound on racket. One possible way could be to decode the audio using libsndfile
(supports just about everything except mp3) and then hook it up with the racket portaudio
library. I found these example bindings for sndfile
over here: https://www.github.com/racket/racket/tree/5bb837661c12a9752c6a99f952c0e1b267645b33/pkgs%2Fracket-doc%2Fffi%2Fexamples%2Fsndfile.rkt\|https://www.github.com/racket/racket/tree/5bb837661c12a9752c6a99f952c0e1b267645b33/pkgs%2Fracket-doc%2Fffi%2Fexamples%2Fsndfile.rkt
Have not been able to get them working yet, due to a few errors along with a few parts where I didn’t quite understand the code.
It’s also worth noting that sndfile
is planning to add mp3 support soon, since the patents for it have already expired.