Mark Sibly

Forum Replies Created

Viewing 15 posts - 1,336 through 1,350 (of 1,431 total)
  • Author
    Posts
  • in reply to: Streaming Audio #1259

    Mark Sibly
    Keymaster

    That’s the easy part – the syncing is where it gets tricky!

    App code can’t just WriteSamples at will, it will need to halt to allow ReadSamples to catch up or the buffer will get ahead. On the other hand, if app code can’t WriteSamples fast enough, well yer basically hosed…

    IMO, the best thing to do is start with getting the Callback moved to the monkey side, via either polling or signalling, so the audio device pulls data from SDL code running on it’s own audio thread, which pulls data from mx2 code running on the GUI thread.

    Then you could perhaps look at using a fiber to provide synchronous/blocking writes to audio. This way, the fiber can block, not the callback.

    And it’s probably time to add Deque I guess…

    Just some thoughts!

    in reply to: BUG compiling from some folders #1244

    Mark Sibly
    Keymaster

    Can you post an issue at github for this?

    I’m gonna start trying to use that from now on!

    in reply to: Streaming Audio #1237

    Mark Sibly
    Keymaster

    > Or yes, it could block and wait for a monkey2 signal to say the copy has been performed on main thread…

    Not quite sure what you mean here, but the native callback should never block. It should just copy in audio data, signal the gui/mx2 thread that it needs more data, and return ASAP.

    In a polled scenario, the mx2 polling code could just check a flag, but sync signaling is nicer – see native process.cpp, esp:

    int callback=g_mojo_app_AppInstance_AddAsyncCallback( finished );

    …and…

    postEvent( callback|INVOKE|REMOVE );

    AddAsyncCallback is called on the main thread at setup time, while postEvent is called by native code running in it’s own thread.

    Here, ‘finished’ is an mx2 function that gets called when the process is finished.

    For an audio mixer, ‘finished’ would be something like ‘fillBuffer’ and postEvent would be called once native code has copied out the last buffer. You could in fact double buffer here (on the native thread) and call postEvent after flipping buffers but before copying audio data. This would help allow native/mx2 threads to run concurrently.

    in reply to: Referencing New (Constructor) #1235

    Mark Sibly
    Keymaster

    Unfortunately, you’ll currently have to use the ‘Init’ approach for this particular code.

    The problem is that you can’t currently have ‘complex’ parameter expressions when you chain new’s together (ie: the ‘New Image[]( image )’ ) – mainly because you can’t in C++, and mx2 New currently maps directly to c++ ctors. Which seemed like a good idea at the time but has proven to have some serious limitations.

    I do plan to eventually fix this though, hopefully soon!

    in reply to: Streaming Audio #1234

    Mark Sibly
    Keymaster

    Nice idea, but I think you’ll run into problems with the complete lack of thread sync in mx2, as the audio callback is called on a different thread (I think).

    An alternative would be to have the SDL callback trigger a ‘main thread’ callback. There’s actually a kludgy behind-the-scenes way to do this in mojo.app and mojo.process that I eventually want to wrap in a nicer way. This would only work as long as the main thread was running fast enough of course.

    Alias SDL_AudioCallback:Void(Void Ptr,UByte Ptr,Int)

    Thanks, fixed.

    Can I cast a monkey2 class to Void Ptr?

    Nope, but you can wrap the object in a struct and pass a pointer to that. I use this in the pixmap loader to pass the mx2 stream as ‘context’ void ptr, something like:

    Casting object to void ptr may happen eventually, but it’s potentially dangerous for a number of reasons. I like having the struct wrapper as it ensures the object is wrapped in a variable and will be kept ‘alive’ while the callback is happening and not inadvertantly collected, similar to sticking something in a global to keep it alive.

    in reply to: Collision module and performance #1230

    Mark Sibly
    Keymaster

    There is also a bit of an issue with markdown ‘#’ clashing with ‘#’ for the preprocessor…need to come up with some kind of work around for this.

    in reply to: Collision module and performance #1229

    Mark Sibly
    Keymaster

    There are a few issues…but what’s hanging the compiler is a stray ‘=’ before a ‘#End’ in quadtree, ie: search for ‘=#’.

    Will fix!

    in reply to: rebuildall only rebuilds release mode #1214

    Mark Sibly
    Keymaster

    According to the above, the debug modules are building OK.

    Can you post the output from the unsuccessful debug build of the app?

    If it thinks there are files missing, can you check if they are there or not?

    in reply to: rebuildall only rebuilds release mode #1212

    Mark Sibly
    Keymaster

    Please post the console output from a rebuildall.

    in reply to: If Then \nl – fail? #1203

    Mark Sibly
    Keymaster

    ‘Then’ was originally intended to be for ‘one liner’ Ifs only, but given it turned out to be optional I have no problems supporting it for ‘block ifs’ too if there are no complaints. This is monkey1 behaviour too.

    in reply to: Collision module and performance #1183

    Mark Sibly
    Keymaster

    I mean ‘Operator+=’, not ‘Operator+’, eg:

    If you’ve defined an Operator+() but not an Operator+=(), mx2 will rewrite…

    p+=v

    …as…

    p=p+v

    …but if you’ve defined Operator+=(), mx2 will use that instead.

    I’m guessing Top is the same as First?

    Top is really ‘last’, ie: the last thing pushed/added. blah[0] is ‘first’. You can use a stack pretty much how you’d use a c++ std::vector or java ‘ArrayList’, ie: index with [i], so blah[blah.Length-1] is also ‘last’ or ‘Top’.

    in reply to: Collision module and performance #1181

    Mark Sibly
    Keymaster

    Also, just cleaning up another issue and there appear to be several places in timelinefx where you use ‘Stack’ or List’ without any type, eg:

    Method GetObjectsInBox:Stack(area:tlBox, Layer:Int[], GetData:Int = False)

    This was compiling before but wont with the next release. Full list of errors with my release…

    D:/dev/monkey2/modules/timelinefx/quadtree.monkey2 [246] : Error : Type ‘Stack<T?> is generic
    D:/dev/monkey2/modules/timelinefx/quadtree.monkey2 [291] : Error : Type ‘Stack<T?> is generic
    D:/dev/monkey2/modules/timelinefx/quadtree.monkey2 [841] : Error : Type ‘Stack<T?> is generic
    D:/dev/monkey2/modules/timelinefx/quadtree.monkey2 [936] : Error : Type ‘Stack<T?> is generic
    D:/dev/monkey2/modules/timelinefx/collision.monkey2 [1068] : Error : Type ‘List<T?> is generic

    in reply to: Collision module and performance #1180

    Mark Sibly
    Keymaster

    Have a look at Operator+=

    Mx2 will synthesize one for you, but you can provide your own too.

    in reply to: Collision module and performance #1165

    Mark Sibly
    Keymaster

    That’s interesting, so if I have a method in a struct it shouldn’t modify the field values I should create a new struct with updated values and return that?

    It’s up to you! I was really just trying to think up a good example for ‘when should something be a struct’, and I think if a type can be implemented as an immutable type it’s possibly a good candidate. On the other hand, if a field of a type needs to be modified independently in some way, maybe it’s not a good candidate. It’s sounding like a crapper example each time I explain it…

    I do prefer to make as much stuff as immutable as possible myself though. Having methods return a ‘new’ value is more flexible and safer than methods that modify ‘Self’ IMO, as you don’t have to think about what a method or operator might be modifying (ie: nothing!), but that’s more a stylistic thing than a speed thing. But it’s also true that structs do make immutable types easier/more efficient to write, so rock on structs!

    And with immutable types and operator loading, math can look completely ‘natural’, eg:

    e->Position=matrix * pos * u.Cross( v ) + offset…etc

    …and just like int/float math, you don’t have to worried about anything be inadvertantly modified along the way.

    There likely *is* some cost overhead for this amount of simplicity/flexibility, but c++ deals incredibly well with most of it, esp. with structs, so IMO it’s worth it.

    in reply to: error: 't_std_geom_Vec2_1' does not name a type #1154

    Mark Sibly
    Keymaster

    Ok, this should be being caught by mx2 not gcc, will fix, but the problem is you need to use ‘Vec2f’ not just ‘Vec2’.

    Vec2 is generic so must  be used with a type argument (like List or Stack).

    Vec2f is an alias for Vec2<Float>, similar to the way IntList is an alias for List<Int> etc.

Viewing 15 posts - 1,336 through 1,350 (of 1,431 total)