Open SebastianGroesswang opened 2 years ago
I can't tell without seeing more of your code where the problem is.
But for transposing the audio you should be able to do that with no changes. If you add %%MIDI transpose -2
to the top of your ABC string it should play two half steps lower than written.
And I apologize for the state of the audio API. It grew and evolved. I'm currently working on a wrapper that will simplify the calling of all the audio functions. I'm not sure when it will be ready, though.
im sry for the late response...
import React, {Component} from 'react';
import 'abcjs/abcjs-midi.css';
import abcjs from 'abcjs/midi';
import { width } from '@mui/system';
import PropTypes from 'prop-types';
import { withStyles } from '@mui/styles';
import { Button, formLabelClasses, IconButton } from '@mui/material';
import { ArrowBack, FormatColorResetOutlined, Pause, PlayArrow, Replay } from '@mui/icons-material';
class ABCPlayer extends Component {
constructor(props){
super(props)
this.state = {
alreadyPlaying: false
}
}
render(){
const {classes} = this.props;
return(
<div className={classes.content}>
<div className={classes.header}>
<IconButton color="primary" aria-label="go back to scan" onClick={() => {this.synthController.pause();this.timingCallbacks.stop();this.props.returnBack()}}>
<ArrowBack/>
</IconButton>
</div>
<div style={{backgroundColor: 'white'}}>
<div id="paper" ></div>
</div>
<div id="audio"/>
<div className={classes.alignCenterBottom}>
<IconButton color="primary" aria-label="go back to scan" onClick={() => {
if(this.state.alreadyPlaying === false){
this.synthController.play()
this.timingCallbacks.start()
this.setState({alreadyPlaying: true})
}
}}>
<PlayArrow/>
</IconButton>
<IconButton color="primary" aria-label="go back to scan" onClick={() => {
this.synthController.pause()
this.timingCallbacks.pause()
this.setState({alreadyPlaying: false})
}}>
<Pause/>
</IconButton>
<IconButton color="primary" aria-label="go back to scan" onClick={() => {
this.synthController.restart()
this.timingCallbacks.reset()
}}>
<Replay/>
</IconButton>
</div>
</div>
)
}
componentDidMount() {
this.synthController = new abcjs.synth.SynthController()
this.synthController.load("#audio", {}, {
displayLoop: false,
displayRestart: false,
displayPlay: false,
displayProgress: false,
displayWarp: false
});
this.visualObj = abcjs.renderAbc(
"paper",
this.props.abc,
{
responsive : "resize",
staffwidth: 300,
wrap: {
minSpacing: 1.2,
maxSpacing: 2.7,
preferredMeasuresPerLine: 2
}
}
)
this.timingCallbacks = new abcjs.TimingCallbacks(this.visualObj[0], {eventCallback: (ev) => {console.log(ev)}});
this.synth = new abcjs.synth.CreateSynth();
var myContext = new AudioContext();
this.synth.init({
audioContext: myContext,
visualObj: this.visualObj[0],
options: {
pan: [ -0.3, 0.3 ],
}
}).then((response) => {
this.synthController.setTune(this.visualObj[0], true,
{
onEnded: () => {console.log("stopped"); this.setState({alreadyPlaying: false})}, //onEnded does not work
midiTranspose: this.props.transpose,
program: 0
}
).then(
() => console.log("audio reloaded")
)
}).catch(function (reason) {
console.log(reason)
});
}
};
ABCPlayer.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(ABCPlayer);
this is my component i have coded
The abc transpose parameter sounds like a good workaround but i would rather use the transpose option of the SynthController. My intention is to hold the abc string as short as it can be. And the midi parameter seems quite difficult to understand.
I might not be following this exactly but I see you setting the tune when the component is mounted, but I don't see it being recreated if this.props.transpose
changes. Is that variable dynamic because if so setTune
needs to be called again when it changes.
Other than that, your code matches the code in https://paulrosen.github.io/abcjs/examples/basic-transpose.html so I think it should work.
The first thing I'd do is put console.log(this.props.transpose)
just above setTune
to make sure the expected value is being passed. If so, I'd put a breakpoint at the top of synth/abc_midi_sequencer.js to make sure options.midiTranspose
contains the correct value.
this.props.transpose
will not be changed after this component has been mounted. The transposing workes with no problems at all. Cause after this.synthController.play()
has been called the audio which will be played is in the perfect pitch.
But the problem here is after I call this.synthController.pause()
and then calling this.synthController.play()
again. Nothing will be played.
And yes I took the basic-transpose.html as example and coded after it. But one thing is different is I directly call the synthController.play/.pause methods and not load the buttons, progressbar etc in #audio
.
Oh, I see. I didn't understand. I'll see if I can reproduce.
What version of abcjs did you specify In package.json
? I suspect it is an old version because the import has changed from import abcjs from 'abcjs/midi';
to import abcjs from 'abcjs';
If you change it to 6.0.0-beta.36
do you still have the problem?
before i was using 5.12.0
Even if I adopt the new version and the other import, the same bug occurs.
I will try for a stable build the workaround with the %MIDI header parameter in the abc string.
I also ran into this problem with version 6.0.2, after pausing the music successfully, calling play() will not work, but if you carry on calling play() and pause(), and then play() again, it works :)
I am trying to find a workaround for this.
Best regards, Ben
just like I said, you can call pause-play-pause to implement the PAUSE operation as a workaround , and then play() works well.
I have the same problem with 6.3.0. The "pause play pause play" Workaround does it's job, but when I try to restart instead with "pause play pause restart play", the position slider starts at the beginning, but the playback contiunues at the position where it was paused. Is there any news about this issue?
Kind regards Thomas
First of all great work and thank you for this public library..
I am currently working on an react application which displays and plays a specific music sheet. In other words a play along of abc strings. I was using the basic
CreateSynth()
until I had to transpose the audio.So I changed to
SynthController()
. I used a custom bar to display the play, pause and restart button, because it was still present from theCreateSynth()
job.After I called
synthController.play()
the music started playing till i called thesynthController.pause()
method. Now I want to continue from the pause and due to that I calledsynthController.play()
again. And nothing happened.Am I using the wrong calls of methods or could this be a bigger bug?