Implementing test recording

PennController for IBEX Forums Support Implementing test recording

Viewing 6 posts - 1 through 6 (of 6 total)
  • Author
    Posts
  • #8099
    dod
    Participant

    Hi!

    I’m coding a production experiment and I’m trying to implement a test recording. The idea is to let participants check and adjust their audio/mic quality before starting. However, I’m having a couple of problems.

    – I want the participants to listen to their recording; then, decide whether to do another audio test or move on to the task. To do so, I added a newMediaRecorder as part of the success code block of the test.clicked on the ‘Record again’ button. But it doesn’t seem to work. I cannot spot any errors in the syntax, so I’m a bit lost. Is there any particular reason why it’s not working?

    – Ideally, I want to give participants the chance to change their settings until the audio is clear. I thought about nesting a defined number of test.clicked commands with success/failure (if I manage to make it work!). But I was wondering if there is a less complicated way to implement this kind of loop command.

    – Last minor thing – and this time I most likely made some dumb errors in the syntax. When I press the “Play” button, it doesn’t wait for the audio to be completely played before moving to the next trial.

    Thank you in advance for any suggestions! And sorry if it is redundant, but I couldn’t find any post on the topic.

    Here’s the code so far:

    InitiateRecorder("").label("init")
    
    // Let's participants check audio quality
    newTrial( "audio_check" ,
        defaultText.css({"margin-bottom":"1em"}).center()
        ,
        // Instructions
        newText("instr-1", 
            "Before starting..."
            .print()
        ,
        newButton("Start").center().print().wait().remove()
        ,
        clear()
        ,
        // Recording test 1
        newMediaRecorder("audiotest1", "audio").log().record()
        ,
        newButton("done","Done").center().print().wait().remove()
        ,
        getMediaRecorder("audiotest1").stop()
        ,
        // Listen to the audio
        newText("thanksPlay","Thank you! Press PLAY to listen to the audio.").print()
        ,
        newButton("Play")
            .callback(
                getMediaRecorder("audiotest1")
                    .play()
                    .wait("playback"))
            .center().print().wait()
        ,
        clear()
        ,
        // Record again or move on
        newText("testagain",
            "If it seems to you that the audio is not clear and/or there is too much background noise...")
        ,
        newText("next",
            "If the audio seems clear and of good quality, press CONTINUE")
        ,
        getText("testagain").print()
        ,
        newButton("recordagain","Record again").center().print()
            .test.clicked()
            .success(
                // test 2
                newMediaRecorder("audiotest2", "audio").log().record(),
                getButton("done").center().print().wait().remove(),
                getMediaRecorder("audiotest2").stop(),
                getText("thanksPlay").print(),
                newButton("play2", "Play").callback(getMediaRecorder("audiotest2").play().wait("playback")).center().print().wait(),
                clear(),
                // Record again or move on
                getText("testagain").print(),
                getButton("recordagain").center().print()
                    .test.clicked()
                    .success(
                        // test 3?
                        )
                    .failure(),
                getText("next").print()
                )
            .failure()
        ,
        // or move on
        getText("next").print()
        ,
        newButton("Continue").center().print().wait()
    )
    UploadRecordings("upload")
    #8101
    Jeremy
    Keymaster

    Hi,

    Why don’t you use .print() on the MediaRecorder element and let participants use the interface to freely record and play back? It would save you a lot of coding

    Re. looping: you are already using callback on the Button element “Play” so that’s a command you could use (on another button) to implement a loop-like behavior too. Actually you don’t need to, and probably shouldn’t, use callback on the “Play” button itself, because that’s what makes the script go on without waiting for playback to finish

    Re. test.clicked: you place it immediately after creating the Button element, so of course the participant won’t have time to click the button in the 0-1ms it takes the script to move from executing the newButton line to executing the .test.clicked line, and so the test will always fail

    Putting this all together, here’s the simple way to implement your test:

    newTrial( "audio_check" ,
        defaultText.css({"text-align":"center", "margin-bottom":"1em"}).center().print()
        ,
        newText("instr-1", "Before starting...")
        ,
        newMediaRecorder("audiotest1", "audio")
            .log()
            .print()
            .wait()
        ,
        newText("testagain", "If it seems to you that the audio is not clear and/or there is too much background noise...")
        ,
        newText("next", "If the audio seems clear and of good quality, press CONTINUE")
        ,
        newButton("Continue").center().print().wait()
    )

    If you really want to implement a custom interface, you could do something like this:

    newTrial( "audio_check" ,
        defaultText.css({"text-align":"center", "margin-bottom":"1em"}).center().print()
        ,
        defaultButton.center()
        ,
        newText("instr-1", "Before starting...")
        ,
        newButton("trigger", "Do a test recording")
            .callback(
                clear()
                ,
                newMediaRecorder("audiotest1", "audio").log().record()
                ,
                newButton("Stop").print().wait().remove()
                ,
                getMediaRecorder("audiotest1").stop()
                ,
                newButton("Play").print().wait().remove()
                ,
                getMediaRecorder("audiotest1").play().wait("playback")
                ,
                newText("If it seems to you that the audio is not clear and/or there is too much background noise...")
                ,
                newText("If the audio seems clear and of good quality, press CONTINUE")
                ,
                getButton("trigger").print()  // Clicking this will execute the callback sequence again
                ,
                getButton("Continue").print() // Print the button now: clicking it will end the trial (=validate the wait command)
            )
            .print()
        ,
        // This button will only be printed at the end of a test,
        // So the script won't have a chance to move past the wait command until then
        newButton("Continue").css("margin-top","1em").wait()
    )

    Jeremy

    #8103
    dod
    Participant

    Hi Jeremy, thanks for the quick reply, as always!

    I didn’t think at all about the print option, to be fair. I kept the recorder hidden in the experimental trials, and now I was over-complicating things. At the moment, I don’t see any particular reason for hiding it in the audio check as well. So I’ll go for printing it, and that’s it. If I change my mind later on, I know I can start from your custom interface code (I tried it, and I see your point).

    At least now I’ve learned not to use the callback on the play button 🙂
    Just another naive question that might come in handy in the future. So, in a code like that with the newMediaRecorder in the looped callback command, PCIbex will play and save different recordings even if the mediarecorder has the same name? I mean, at the end of the day, would I have X zip files with the same “audiotest1” from a same participant, or will they somehow be labelled sequentially?

    As for the test.clicked, my bad, there was indeed an error in the syntax. I checked previous codes, and it’s true that I had always put the test in the wait brackets of buttons/dropdowns (something like newButton(“X”).wait(getButton(“X”).test.clicked…). And at the point of course it worked. Sorry again for the silly questions – I’m still pretty new with all the coding-related stuff!

    Thank you

    #8104
    Jeremy
    Keymaster

    Hi,

    I’m pretty sure you would only get recording per MediaRecorder, only the most recent one

    Your questions make perfect sense to me! But, unfortunately, PennController’s reasoning is much more blunt, it doesn’t try to understand the reasoning behind the code

    Jeremy

    #8106
    dod
    Participant

    But it definitely serves its purpose, so far!

    So, I guess the same logic applies when printing the MediaRecorder and then uploading it – the zip name I got in the results line refers only to the most recent attempt, doesn’t it?

    Dod

    #8108
    Jeremy
    Keymaster

    Hi Dod,

    Yes, whichever method you use, one MediaRecorder element means one audio file, containing the most recent recording — you should try it out yourself though to double-check. Zip files containing recordings have non-related, unique filenames and may contain one or more recordings (because trials can contain several MediaRecorder elements, and uploads can take place after several trials too) but the audio files in the zip files are indeed named after the name of the MediaRecorder

    Jeremy

Viewing 6 posts - 1 through 6 (of 6 total)
  • You must be logged in to reply to this topic.