我正在开展一个项目,我需要在pitches
中显示GraphView
单词(来自歌曲)。我写了一个program
,它会从一首歌中获得pitches
并从中创建一个.txt file
。
然后我写了一个类,它读取file
并从中创建list
。最后,我会得到list
words
和word
包含pitches
。在MakePitchesList
中,您可以看到歌曲中pitches
输出的内容。我在每一行都有0,14:23281,61
。该行的第一部分是timeOccurance
意思,当听到这个音高时,第二部分是音高本身。因此,在此示例中,timeOccurance
将为0,14
并在给定时间23281,61
进行推销。
以下是从wordsList
中生成pitch .txt file
的三个类。
public class Pitch{
float occuranceTime;
float pitch;
public void setOccuranceTime(float occuranceTime) {
this.occuranceTime = occuranceTime;
}
public float getOccuranceTime() {
return occuranceTime;
}
public void setPitch(float pitch) {
this.pitch = pitch;
}
public float getPitch() {
return pitch;
}
}
public class MakePitchesList {
String[] pitches;
List<Pitch> listOfPitches = new ArrayList<Pitch>();
public List<Pitch> getListOfPitches(){
getPitches();
for (String pitchString: pitches) {
Pitch pitch = new Pitch();
makeListOfPitches(pitch, pitchString);
}
return listOfPitches;
}
public void makeListOfPitches(Pitch pitch, String pitchString){
pitch.setPitch(getPitchesInfo(pitchString, 1));
pitch.setOccuranceTime(getPitchesInfo(pitchString, 0));
listOfPitches.add(pitch);
}
public String[] getPitches() {
pitches = pitchesRaw.split("\\r?\\n");
return pitches;
}
private float getPitchesInfo(String pitch, int position){
String[] frequencyAndTime = pitch.split("\\:");
if(position == 0){
return Float.parseFloat(frequencyAndTime[0].replace(',', '.'));
}
if(position == 1){
return Float.parseFloat(frequencyAndTime[1].replace(',', '.'));
}
else return 0;
}
String pitchesRaw =
"0,14:23281,61\n" +
"0,23:53,65\n" +
"0,37:72,53\n" +
"0,56:86,09\n" +
"0,60:88,58\n" +
"0,65:87,45\n" +
"0,70:87,11\n" +
"0,74:89,56\n" +
"0,79:96,22\n" +
"0,84:23288,24\n" +
"0,88:103,92\n" +
"0,93:107,46\n" +
"0,98:108,02\n" +
"1,02:107,51\n" +
"1,07:104,92\n" +
"1,11:105,94\n" +
"1,16:106,40\n" +
"1,21:104,43\n" +
"1,25:104,93\n" +
"1,30:108,01\n" +
"1,35:316,81\n" +
"1,39:103,98\n" +
"1,44:23297,42\n" +
"1,49:23357,42\n" +
"1,53:23359,74\n" +
"1,58:23393,04\n" +
"1,63:23244,18\n" +
"1,67:23220,51\n" +
"1,72:23250,06\n" +
"1,76:23288,84\n" +
"1,81:23241,81\n" +
"1,86:23295,22\n" +
"1,90:23268,04\n" +
"1,95:23252,78\n" +
"2,00:23224,22\n" +
"2,04:23429,71\n" +
"2,09:23214,58\n" +
"2,14:23240,70\n" +
"2,18:23237,71\n" +
"2,23:23231,22\n" +
"2,28:23222,77\n" +
"2,32:23239,73\n" +
"2,37:23235,98\n" +
"2,41:23222,16\n" +
"2,46:23224,01\n" +
"2,51:23214,26\n" +
"2,55:23223,20\n" +
"2,60:23234,11\n" +
"2,65:23221,65\n" +
"2,69:23213,45\n" +
"2,74:23217,44\n" +
"2,79:23235,93\n" +
"2,83:11122,79\n" +
"2,88:23234,58\n" +
"2,93:23229,52\n" +
"2,97:23255,48\n" +
"3,02:23254,44\n" +
"3,07:23355,41\n" +
"3,44:105,48\n" +
"3,48:115,45\n" +
"3,53:117,78\n" +
"3,58:127,36\n" +
"3,62:131,24\n" +
"3,67:130,33\n" +
"3,72:131,93\n" +
"3,76:127,32\n" +
"3,81:117,18\n" +
"3,85:117,80\n" +
"3,90:117,15\n" +
"3,95:121,04\n" +
"3,99:131,22\n" +
"4,04:130,38\n" +
"4,09:130,34\n" +
"4,13:129,57\n" +
"4,18:120,38\n" +
"4,23:121,06\n" +
"4,32:100,12\n" +
"4,37:23483,16\n" +
"4,41:112,95\n" +
"4,46:23448,04\n" +
"4,50:23396,09\n" +
"4,55:23292,90\n" +
"4,60:117,21\n" +
"4,64:116,58\n" +
"4,69:116,62\n" +
"4,74:119,18\n" +
"4,78:131,19\n" +
"4,83:130,34\n" +
"4,88:129,59\n" +
"4,92:132,64\n" +
"4,97:129,68\n" +
"5,02:132,71\n" +
"5,06:133,57\n" +
"5,11:128,94\n" +
"5,15:131,09\n" +
"5,20:132,75\n" +
"5,25:129,68\n" +
"5,29:131,26\n" +
"5,34:131,22\n" +
"5,39:130,38\n" +
"5,43:146,01\n" +
"5,48:140,43\n" +
"5,57:23450,16\n" +
"5,62:130,46\n" +
"5,67:132,02\n" +
"5,71:23243,22\n" +
"5,76:23456,28\n" +
"5,85:23246,64\n" +
"5,90:23274,97\n" +
"5,94:23310,30\n" +
"5,99:23229,71\n" +
"6,08:23214,33\n" +
"6,13:23221,53\n" +
"6,18:23263,48\n" +
"6,22:23213,17\n" +
"6,27:23235,04\n" +
"6,32:23222,02\n" +
"6,36:23214,90\n" +
"6,41:23230,05\n" +
"6,46:23212,55\n" +
"6,50:23221,33\n" +
"6,55:23226,70\n" +
"6,59:23217,07\n" +
"6,64:23272,07\n" +
"6,69:11102,74\n" +
"6,73:23263,38\n" +
"6,78:23217,53\n" +
"6,97:23243,63\n" +
"7,11:23214,11\n" +
"7,15:23229,58\n" +
"7,20:23225,70\n" +
"7,24:23244,82\n" +
"7,29:23243,09\n" +
"7,34:23249,66\n" +
"7,38:23226,67\n" +
"7,43:23246,31\n" +
"7,48:23258,55\n" +
"7,52:23230,34\n" +
"7,57:23225,60\n" +
"7,62:23280,25\n" +
"7,66:23238,08\n" +
"7,71:23221,47\n" +
"7,85:117,87\n" +
"7,89:117,19\n" +
"7,94:117,21\n" +
"7,99:117,21\n" +
"8,03:116,57\n" +
"8,08:119,10\n" +
"8,13:44,01\n" +
"8,17:129,52\n" +
"8,22:132,72\n" +
"8,27:143,19\n" +
"8,31:141,13\n" +
"8,36:139,35\n" +
"8,45:132,82\n" +
"8,50:129,76\n" +
"8,54:130,43\n" +
"8,68:94,20\n" +
"8,78:132,70\n" +
"8,82:130,43\n" +
"8,87:129,60\n" +
"8,92:130,56\n" +
"8,96:128,92\n" +
"9,01:119,19\n" +
"9,06:118,45\n" +
"9,10:103,41\n" +
"9,15:103,41\n" +
"9,20:103,89\n" +
"9,24:106,46\n" +
"9,29:214,93\n" +
"9,33:23427,95\n" +
"9,38:23356,01\n" +
"9,43:106,41\n" +
"9,47:100,57\n" +
"9,52:106,39\n" +
"9,57:104,40\n" +
"9,61:99,70\n" +
"9,66:106,42\n" +
"9,71:103,50\n" +
"9,75:104,47\n" +
"9,80:106,97\n" +
"9,85:99,68\n" +
"9,89:23454,22\n" +
"9,94:23299,56\n" +
"9,98:23275,30\n" +
"10,03:23222,72\n" +
"10,08:23246,09\n" +
"10,12:23221,14\n" +
"10,17:23240,54\n" +
"10,22:23246,81\n" +
"10,26:23224,74\n" +
"10,31:23249,41\n" +
"10,36:23214,79\n" +
"10,40:23213,46\n" +
"10,45:23259,51\n" +
"10,50:23217,39\n" +
"10,54:23215,36\n" +
"10,59:23224,87\n" +
"10,63:23242,27\n" +
"10,68:23270,82\n" +
"10,73:23243,19\n" +
"10,77:23222,75\n" +
"10,82:23268,78\n" +
"10,87:23321,62\n" +
"10,91:23259,65\n" +
"11,05:23226,24\n" +
"11,10:23222,92\n" +
"11,15:23218,83\n" +
"11,19:23211,71\n" +
"11,24:11112,28\n" +
"11,28:23261,03\n" +
"11,33:23265,31\n" +
"11,38:23245,92\n" +
"11,42:57,09\n" +
"11,61:103,45\n" +
"11,66:103,91\n" +
"11,70:102,02\n" +
"11,75:107,96\n" +
"11,80:105,43\n" +
"11,84:104,46\n" +
"11,89:116,64\n" +
"11,94:115,99\n" +
"11,98:114,77\n" +
"12,03:121,72\n" +
"12,07:123,16\n" +
"12,12:125,12\n" +
"12,17:128,85\n" +
"12,21:120,37\n" +
"12,26:116,52\n" +
"12,31:130,55\n" +
"12,35:131,06\n" +
"12,40:131,89\n" +
"12,45:128,88\n" +
"12,49:23397,75\n" +
"12,59:118,45\n" +
"12,63:116,54\n" +
"12,68:119,70\n" +
"12,72:115,45\n" +
"12,77:115,30\n" +
"12,82:119,86\n" +
"12,86:116,59\n" +
"12,91:114,13\n" +
"12,96:119,04\n" +
"13,00:118,47\n" +
"13,05:115,38\n" +
"13,10:128,92\n";
}
public class MakeWordsList {
List<Pitch> pitches;
public List<List<Pitch>> getWordsList(List<Pitch> pitchList) {
return makeWordsList(pitchList);
}
List<Pitch> oneWord = new ArrayList<>();
List<List<Pitch>> wordList = new ArrayList<>();
public List<List<Pitch>> makeWordsList(List<Pitch> pitchList){
pitches = pitchList;
int pauseCounter = 0;
for (int i = 0; i < pitchList.size(); i++) {
if(pitchList.get(i).getPitch() > 10000){
pauseCounter++;
} else {
if(pauseCounter > 0){
if(pauseCounter >= 5){
wordList.add(oneWord);
oneWord = new ArrayList<>();
}
pauseCounter = 0;
}
oneWord.add(pitchList.get(i));
}
}
if(oneWord.size() > 0){
wordList.add(oneWord);
}
return wordList;
}
}
现在从那个wordsList
我创建一个scrollable GraphView
,在纸上看起来像这样。
现在我已为GraphView
:MinX = -0.8; MaxX = 0.4
设置了界限。这样我在屏幕上一次显示1秒。然后我启动一个线程,这样它每隔100毫秒将coordinates
的{{1}}改为0.1,每秒加起来为1。
这是代码:
GraphView
总结一下代码的作用:它从节距中获取 public class SongPlayer extends AppCompatActivity {
private Viewport graphViewPort;
private Handler handler;
private Runnable runnable;
private GraphView graph;
private DataPoint[] points;
private LineGraphSeries<DataPoint> series;
private int seriesNr;
final static double GRAPH_STARTING_X = -0.8;
final static double GRAPH_ENDING_X = 0.4;
private double orderNr = GRAPH_STARTING_X;
private List<Pitch> pitchesList;
List<List<Pitch>> wordsList;
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.song_player);
Intent intent = getIntent();
//Get Textview and Button
playRecordButton = (ImageButton) findViewById(R.id.playRecord);
//Initialize pitches and words
MakePitchesList listOfPithes = new MakePitchesList();
MakeWordsList listOfWords = new MakeWordsList();
pitchesList = listOfPithes.getListOfPitches();
wordsList = listOfWords.getWordsList(pitchesList);
//Initialize graph
graph = (GraphView) findViewById(R.id.graph);
initGraph();
//ViewPort
graphViewPort = graph.getViewport();
//Handler
handler = new Handler();
playRecordButton.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionevent) {
final int action = motionevent.getAction();
if (action == MotionEvent.ACTION_DOWN) {
//Start playing audio
playMedia();
//Start moving graph
drawAndMoveGraph();
} else if (action == MotionEvent.ACTION_UP) {
//Stop moving graph and set them to the beginning
resetGraph();
//Stop Playing audio
stopAudio();
}//end else
return false;
} //end onTouch
}); //end b my button
}
private void drawAndMoveGraph(){
runnable = new Runnable() {
public void run() {
System.out.println(orderNr);
graphViewPort.setMinX(orderNr);
graphViewPort.setMaxX(orderNr + 1);
graph.invalidate();
if(pitchesList.size() != orderNr){
orderNr = orderNr + 0.1;
// System.out.println(orderNr);
}
handler.postDelayed(this, 100);
}
};
runnable.run();
}
private void initGraph(){
for (int i = 0; i < wordsList.size(); i++) {
seriesNr = 0;
points = new DataPoint[wordsList.get(i).size()];
for (Pitch pitch: wordsList.get(i)) {
points[seriesNr] = new DataPoint(pitch.getOccuranceTime(), pitch.getPitch());
seriesNr++;
}
series = new LineGraphSeries<>(points);
series.setThickness(15);
graph.addSeries(series);
}
//VocalTestPoints
PointsGraphSeries<DataPoint> series = new PointsGraphSeries<>(new DataPoint[] {
new DataPoint(0, 50),
new DataPoint(0, 75),
new DataPoint(0, 100),
new DataPoint(0, 125),
new DataPoint(0, 150),
new DataPoint(0, 175),
new DataPoint(0, 200),
new DataPoint(0, 225),
new DataPoint(0, 250),
new DataPoint(0, 275),
});
series.setSize(5);
series.setColor(Color.YELLOW);
graph.addSeries(series);
// set manual X bounds
graph.getViewport().setYAxisBoundsManual(true);
graph.getViewport().setMinY(-50);
graph.getViewport().setMaxY(400);
graph.getViewport().setXAxisBoundsManual(true);
graph.getViewport().setMinX(GRAPH_STARTING_X);
graph.getViewport().setMaxX(GRAPH_ENDING_X); //mitu korraga näeb
graph.getViewport().setScrollable(true);
}
private void playMedia(int songIndex){
StorageUtil storage = new StorageUtil(getApplicationContext());
storage.storeAudio(audioList);
storage.storeAudioIndex(songIndex);
mediaPlayer = new MediaPlayer();
//Reset so that the MediaPlayer is not pointing to another data source
mediaPlayer.reset();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(storage.loadAudio().get(storage.loadAudioIndex()).getData());
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.prepareAsync();
// mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}
});
}
private void stopAudio(){
mediaPlayer.stop();
mediaPlayer.release();
}
private void resetGraph(){
handler.removeCallbacks(runnable);
graphViewPort.setMinX(GRAPH_STARTING_X);
graphViewPort.setMaxX(GRAPH_ENDING_X);
graph.invalidate();
orderNr = GRAPH_STARTING_X;
}
}
,初始化图形,开始监听按钮点击。单击按钮时,它会如上所述开始移动图形并播放音频。
问题是音频和移动wordsList
不同步。对于前10秒左右,它的工作方式应该如此,但graphView
开始落后。如果有人花时间了解所有这些混乱,我真的很感激。