Browse Source

1.删除KSCloudViewController 本地云教练相关
2.权限申请相关功能优化。
3.作品合成播放器相关优化。

Steven 10 tháng trước cách đây
mục cha
commit
14ca7796e5
93 tập tin đã thay đổi với 1140 bổ sung15025 xóa
  1. 28 310
      KulexiuForStudent/KulexiuForStudent.xcodeproj/project.pbxproj
  2. 39 16
      KulexiuForStudent/KulexiuForStudent/Common/Base/AccompanyWebView/AudioEnginePlayer.m
  3. 92 49
      KulexiuForStudent/KulexiuForStudent/Common/Base/AccompanyWebView/KSAccompanyWebViewController.m
  4. 40 21
      KulexiuForStudent/KulexiuForStudent/Common/Base/AccompanyWebView/KSCloudWebManager.m
  5. 62 46
      KulexiuForStudent/KulexiuForStudent/Common/Base/WebView/KSBaseWKWebViewController.m
  6. 71 51
      KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/KSMergeAudioControlView.m
  7. 0 6
      KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/KSMergeAudioControlView.xib
  8. 8 0
      KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/KSPlayerSliderView.m
  9. 27 0
      KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergeAudioAnimation/KSRealtimeAnalyzer.h
  10. 256 0
      KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergeAudioAnimation/KSRealtimeAnalyzer.m
  11. 23 0
      KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergeAudioAnimation/KSSpectrumView.h
  12. 109 0
      KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergeAudioAnimation/KSSpectrumView.m
  13. 7 1
      KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergePlayer/KSMergeEnginePlayer.h
  14. 218 201
      KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergePlayer/KSMergeEnginePlayer.m
  15. 8 2
      KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/VideoPlayerView/KSVideoPlayerView.m
  16. 32 17
      KulexiuForStudent/KulexiuForStudent/Module/Chat/Controller/TXCustom/KSTXBaseChatViewController.m
  17. 0 85
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/BassMidiEngine.h
  18. 0 186
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/BassMidiEngine.m
  19. 0 1131
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bass.h
  20. 0 2272
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bass.txt
  21. 0 43
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bass.xcframework/Info.plist
  22. BIN
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bass.xcframework/ios-arm64_armv7_armv7s/libbass.a
  23. BIN
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bass.xcframework/ios-arm64_i386_x86_64-simulator/libbass.a
  24. 0 424
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bassmidi.h
  25. 0 689
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bassmidi.txt
  26. 0 43
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bassmidi.xcframework/Info.plist
  27. BIN
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bassmidi.xcframework/ios-arm64_armv7_armv7s/libbassmidi.a
  28. BIN
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bassmidi.xcframework/ios-arm64_i386_x86_64-simulator/libbassmidi.a
  29. 0 20
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Controller/KSCloudViewController.h
  30. 0 2219
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Controller/KSCloudViewController.m
  31. 0 33
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/CloudSongMessageModel.h
  32. 0 35
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/CloudSongMessageModel.m
  33. 0 1206
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/FingerList.plist
  34. 0 30
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/KSParseMessageModel.h
  35. 0 13
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/KSParseMessageModel.m
  36. 0 23
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/KSXMLInfoParse.h
  37. 0 324
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/KSXMLInfoParse.m
  38. 0 24
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/KYSourceParseManager.h
  39. 0 145
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/KYSourceParseManager.m
  40. 0 76
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/SubjectFinger.plist
  41. 0 211
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/TBXML.h
  42. 0 952
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/TBXML.m
  43. 0 25
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Channel/TrackChooseView.h
  44. 0 142
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Channel/TrackChooseView.m
  45. 0 113
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Channel/TrackChooseView.xib
  46. 0 23
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Help/CloudFeedbackView.h
  47. 0 126
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Help/CloudFeedbackView.m
  48. 0 325
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Help/CloudFeedbackView.xib
  49. 0 23
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Help/CloudHelpView.h
  50. 0 253
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Help/CloudHelpView.m
  51. 0 131
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Help/CloudHelpView.xib
  52. 0 29
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/JudgePageView.h
  53. 0 176
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/JudgePageView.m
  54. 0 157
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/JudgePageView.xib
  55. 0 36
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/KSCloudSettingView.h
  56. 0 139
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/KSCloudSettingView.m
  57. 0 135
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/KSCloudSettingView.xib
  58. 0 36
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/SettingPageView.h
  59. 0 155
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/SettingPageView.m
  60. 0 190
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/SettingPageView.xib
  61. 0 43
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SoundCheckView/SoundCheckView.h
  62. 0 153
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SoundCheckView/SoundCheckView.m
  63. 0 177
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SoundCheckView/SoundCheckView.xib
  64. 0 38
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SpeedSlider/KSSliderView.h
  65. 0 154
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SpeedSlider/KSSliderView.m
  66. 0 29
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SpeedSlider/KSTrackingSlider.h
  67. 0 70
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SpeedSlider/KSTrackingSlider.m
  68. 0 25
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/StaffView/CloudControlButton.h
  69. 0 132
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/StaffView/CloudControlButton.m
  70. 0 20
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/StaffView/ScoreAnimationView.h
  71. 0 76
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/StaffView/ScoreAnimationView.m
  72. 0 51
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/StaffView/StaffImageDisplayView.h
  73. 0 109
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/StaffView/StaffImageDisplayView.m
  74. 0 39
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/TipsAlert/EvaluateResultAlert.h
  75. 0 144
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/TipsAlert/EvaluateResultAlert.m
  76. 0 391
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/TipsAlert/EvaluateResultAlert.xib
  77. 0 22
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/TipsAlert/NoWiredTipsAlert.h
  78. 0 49
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/TipsAlert/NoWiredTipsAlert.m
  79. 0 121
      KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/TipsAlert/NoWiredTipsAlert.xib
  80. 28 16
      KulexiuForStudent/KulexiuForStudent/Module/Course/AccompanyCourse/Controller/AccompanyDetailViewController.m
  81. 28 17
      KulexiuForStudent/KulexiuForStudent/Module/Course/MusicRoom/Controller/MusicRoomDetailViewController.m
  82. 7 8
      KulexiuForStudent/KulexiuForStudent/Module/Home/Controller/HomeViewController.m
  83. 7 8
      KulexiuForStudent/KulexiuForStudent/Module/Mine/Controller/MineViewController.m
  84. 6 8
      KulexiuForStudent/KulexiuForStudent/Module/Mine/Scan/Controller/KSScanViewController.m
  85. BIN
      KulexiuForStudent/KulexiuForStudent/ToolKit/CloudAccompanyLibrary.framework/CloudAccompanyLibrary
  86. 34 0
      KulexiuForStudent/KulexiuForStudent/ToolKit/CloudAccompanyLibrary.framework/Headers/KSCloudWebViewController.h
  87. BIN
      KulexiuForStudent/KulexiuForStudent/ToolKit/CloudAccompanyLibrary.framework/_CodeSignature/CodeDirectory
  88. BIN
      KulexiuForStudent/KulexiuForStudent/ToolKit/CloudAccompanyLibrary.framework/_CodeSignature/CodeRequirements-1
  89. 3 3
      KulexiuForStudent/KulexiuForStudent/ToolKit/CloudAccompanyLibrary.framework/_CodeSignature/CodeResources
  90. BIN
      KulexiuForStudent/KulexiuForStudent/ToolKit/CloudAccompanyLibrary.framework/_CodeSignature/CodeSignature
  91. 0 1
      KulexiuForStudent/KulexiuForStudent/ToolKit/KSToolLibrary.framework/Headers/KSAQRecordManager.h
  92. 7 3
      KulexiuForStudent/KulexiuForStudent/ToolKit/KSToolLibrary.framework/Headers/RecordCheckManager.h
  93. BIN
      KulexiuForStudent/KulexiuForStudent/ToolKit/KSToolLibrary.framework/KSToolLibrary

+ 28 - 310
KulexiuForStudent/KulexiuForStudent.xcodeproj/project.pbxproj

@@ -304,7 +304,6 @@
 		BC12639A28FF8E1700509E90 /* HomeNewMusicView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC12639928FF8E1700509E90 /* HomeNewMusicView.xib */; };
 		BC12639D28FF8E6D00509E90 /* HomeRecommendMusicView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC12639C28FF8E6D00509E90 /* HomeRecommendMusicView.m */; };
 		BC12639F28FF8E7400509E90 /* HomeRecommendMusicView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC12639E28FF8E7400509E90 /* HomeRecommendMusicView.xib */; };
-		BC1553792C4E73C300F6A151 /* KSToolLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC1553782C4E73C300F6A151 /* KSToolLibrary.framework */; };
 		BC1D02422C0490AB001F6A94 /* KSMuteTipsView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC1D023F2C0490AB001F6A94 /* KSMuteTipsView.xib */; };
 		BC1D02432C0490AB001F6A94 /* KSMuteTipsView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC1D02402C0490AB001F6A94 /* KSMuteTipsView.m */; };
 		BC27A06E280FF56C00F91E27 /* AccompanyEvaluateCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC27A06A280FF56B00F91E27 /* AccompanyEvaluateCell.xib */; };
@@ -595,6 +594,10 @@
 		BC83A8402AD28AA60033D48B /* TenantNotiferNavView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC83A83F2AD28AA60033D48B /* TenantNotiferNavView.xib */; };
 		BC84183F2AC2D96600D8F90E /* PasswordCheckBodyView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC84183E2AC2D96600D8F90E /* PasswordCheckBodyView.m */; };
 		BC8418412AC2D96C00D8F90E /* PasswordCheckBodyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC8418402AC2D96C00D8F90E /* PasswordCheckBodyView.xib */; };
+		BC85A9DF2C6B5268003C1ABE /* KSToolLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC85A9DD2C6B5268003C1ABE /* KSToolLibrary.framework */; };
+		BC85A9E02C6B5268003C1ABE /* CloudAccompanyLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC85A9DE2C6B5268003C1ABE /* CloudAccompanyLibrary.framework */; };
+		BC85A9E62C6B570E003C1ABE /* KSRealtimeAnalyzer.m in Sources */ = {isa = PBXBuildFile; fileRef = BC85A9E22C6B570E003C1ABE /* KSRealtimeAnalyzer.m */; };
+		BC85A9E72C6B570E003C1ABE /* KSSpectrumView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC85A9E42C6B570E003C1ABE /* KSSpectrumView.m */; };
 		BC89AC092AB0840E00B077AF /* TenantRecommendMusicView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC89AC082AB0840E00B077AF /* TenantRecommendMusicView.m */; };
 		BC89AC0B2AB0841400B077AF /* TenantRecommendMusicView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC89AC0A2AB0841400B077AF /* TenantRecommendMusicView.xib */; };
 		BC89AC0E2AB0842B00B077AF /* TenantNewMusicView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC89AC0D2AB0842B00B077AF /* TenantNewMusicView.m */; };
@@ -605,37 +608,6 @@
 		BC89AC1A2AB08FA100B077AF /* TenantMusicCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC89AC182AB08FA100B077AF /* TenantMusicCollectionViewCell.xib */; };
 		BC89AC1D2AB08FE700B077AF /* TenantMusicCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC89AC1C2AB08FE700B077AF /* TenantMusicCellView.m */; };
 		BC89AC1F2AB08FF500B077AF /* TenantMusicCellView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC89AC1E2AB08FF500B077AF /* TenantMusicCellView.xib */; };
-		BC8A4593283DC33400094BBB /* KSCloudViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A4548283DC33400094BBB /* KSCloudViewController.m */; };
-		BC8A4598283DC33400094BBB /* KYSourceParseManager.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A4554283DC33400094BBB /* KYSourceParseManager.m */; };
-		BC8A4599283DC33400094BBB /* TBXML.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A4557283DC33400094BBB /* TBXML.m */; };
-		BC8A459A283DC33400094BBB /* SubjectFinger.plist in Resources */ = {isa = PBXBuildFile; fileRef = BC8A4558283DC33400094BBB /* SubjectFinger.plist */; };
-		BC8A459B283DC33400094BBB /* CloudSongMessageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A4559283DC33400094BBB /* CloudSongMessageModel.m */; };
-		BC8A459C283DC33400094BBB /* KSXMLInfoParse.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A455A283DC33400094BBB /* KSXMLInfoParse.m */; };
-		BC8A459D283DC33400094BBB /* KSParseMessageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A455C283DC33400094BBB /* KSParseMessageModel.m */; };
-		BC8A459E283DC33400094BBB /* FingerList.plist in Resources */ = {isa = PBXBuildFile; fileRef = BC8A455E283DC33400094BBB /* FingerList.plist */; };
-		BC8A459F283DC33400094BBB /* SettingPageView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC8A4563283DC33400094BBB /* SettingPageView.xib */; };
-		BC8A45A0283DC33400094BBB /* JudgePageView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC8A4564283DC33400094BBB /* JudgePageView.xib */; };
-		BC8A45A1283DC33400094BBB /* KSCloudSettingView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A4565283DC33400094BBB /* KSCloudSettingView.m */; };
-		BC8A45A2283DC33400094BBB /* SettingPageView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A4566283DC33400094BBB /* SettingPageView.m */; };
-		BC8A45A3283DC33400094BBB /* JudgePageView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A4567283DC33400094BBB /* JudgePageView.m */; };
-		BC8A45A4283DC33400094BBB /* KSCloudSettingView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC8A4568283DC33400094BBB /* KSCloudSettingView.xib */; };
-		BC8A45A5283DC33400094BBB /* StaffImageDisplayView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A456E283DC33400094BBB /* StaffImageDisplayView.m */; };
-		BC8A45A6283DC33400094BBB /* ScoreAnimationView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A456F283DC33400094BBB /* ScoreAnimationView.m */; };
-		BC8A45A7283DC33400094BBB /* CloudControlButton.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A4570283DC33400094BBB /* CloudControlButton.m */; };
-		BC8A45AA283DC33400094BBB /* TrackChooseView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A4576283DC33400094BBB /* TrackChooseView.m */; };
-		BC8A45AB283DC33400094BBB /* TrackChooseView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC8A4577283DC33400094BBB /* TrackChooseView.xib */; };
-		BC8A45AC283DC33400094BBB /* KSSliderView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A457B283DC33400094BBB /* KSSliderView.m */; };
-		BC8A45AD283DC33400094BBB /* KSTrackingSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A457C283DC33400094BBB /* KSTrackingSlider.m */; };
-		BC8A45AE283DC33400094BBB /* SoundCheckView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A457F283DC33400094BBB /* SoundCheckView.m */; };
-		BC8A45AF283DC33400094BBB /* SoundCheckView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC8A4580283DC33400094BBB /* SoundCheckView.xib */; };
-		BC8A45B0283DC33400094BBB /* CloudHelpView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A4584283DC33400094BBB /* CloudHelpView.m */; };
-		BC8A45B1283DC33400094BBB /* CloudHelpView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC8A4585283DC33400094BBB /* CloudHelpView.xib */; };
-		BC8A45B2283DC33400094BBB /* CloudFeedbackView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A4586283DC33400094BBB /* CloudFeedbackView.m */; };
-		BC8A45B3283DC33400094BBB /* CloudFeedbackView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC8A4588283DC33400094BBB /* CloudFeedbackView.xib */; };
-		BC8A45B4283DC33400094BBB /* EvaluateResultAlert.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC8A458A283DC33400094BBB /* EvaluateResultAlert.xib */; };
-		BC8A45B5283DC33400094BBB /* EvaluateResultAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A458D283DC33400094BBB /* EvaluateResultAlert.m */; };
-		BC8A45B6283DC33400094BBB /* NoWiredTipsAlert.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC8A458E283DC33400094BBB /* NoWiredTipsAlert.xib */; };
-		BC8A45B7283DC33500094BBB /* NoWiredTipsAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8A458F283DC33400094BBB /* NoWiredTipsAlert.m */; };
 		BC8A45C1283DDD7100094BBB /* synthgms.sf2 in Resources */ = {isa = PBXBuildFile; fileRef = BC8A45C0283DDD7100094BBB /* synthgms.sf2 */; };
 		BC8A45C3283DDE5C00094BBB /* CoreMIDI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC8A45C2283DDE5C00094BBB /* CoreMIDI.framework */; };
 		BC8A45C5283DDE6D00094BBB /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC8A45C4283DDE6D00094BBB /* AudioToolbox.framework */; };
@@ -672,11 +644,6 @@
 		BC9AA0DD2ABC434900CD954D /* KSHudLoagingManager.m in Sources */ = {isa = PBXBuildFile; fileRef = BC9AA0D92ABC434900CD954D /* KSHudLoagingManager.m */; };
 		BC9AA0DE2ABC434900CD954D /* KSCustomLoadingView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC9AA0DA2ABC434900CD954D /* KSCustomLoadingView.m */; };
 		BC9AA0DF2ABC434900CD954D /* KSCustomLoadingView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC9AA0DB2ABC434900CD954D /* KSCustomLoadingView.xib */; };
-		BCA1135D28A3A2BB007FAFB9 /* bass.txt in Resources */ = {isa = PBXBuildFile; fileRef = BCA1135A28A3A2BB007FAFB9 /* bass.txt */; };
-		BCA1135E28A3A2BB007FAFB9 /* bass.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = BCA1135B28A3A2BB007FAFB9 /* bass.xcframework */; };
-		BCA1136228A3A2D0007FAFB9 /* bassmidi.txt in Resources */ = {isa = PBXBuildFile; fileRef = BCA1136028A3A2D0007FAFB9 /* bassmidi.txt */; };
-		BCA1136328A3A2D0007FAFB9 /* bassmidi.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = BCA1136128A3A2D0007FAFB9 /* bassmidi.xcframework */; };
-		BCA1136628A3A2EA007FAFB9 /* BassMidiEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA1136528A3A2EA007FAFB9 /* BassMidiEngine.m */; };
 		BCA1136828A3A5CF007FAFB9 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BCA1136728A3A5CF007FAFB9 /* Accelerate.framework */; };
 		BCA193B8282B6094004A585D /* RecentCourseModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA193B7282B6094004A585D /* RecentCourseModel.m */; };
 		BCA353F12859BB2900377661 /* MusicRoomCourseCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCA353EF2859BB2700377661 /* MusicRoomCourseCell.xib */; };
@@ -916,7 +883,6 @@
 		BCF425F72AB991E600BCD942 /* TenantAlbumModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BCF425F62AB991E600BCD942 /* TenantAlbumModel.m */; };
 		BCF472E72AB019CD0032BE16 /* TenantDarkViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCF472E62AB019CD0032BE16 /* TenantDarkViewController.m */; };
 		BCF472EA2AB01AEB0032BE16 /* TenantMoreViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCF472E92AB01AEB0032BE16 /* TenantMoreViewController.m */; };
-		BCFC09CA2C47F6FF009A727F /* CloudAccompanyLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BCFC09C92C47F6FF009A727F /* CloudAccompanyLibrary.framework */; };
 		BCFC09D12C48B3D7009A727F /* KSAccompanyDraftViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCFC09D02C48B3D7009A727F /* KSAccompanyDraftViewController.m */; };
 		BCFC09DA2C48C8DE009A727F /* UserVip.m in Sources */ = {isa = PBXBuildFile; fileRef = BCFC09D82C48C8DD009A727F /* UserVip.m */; };
 		BCFCE44E28DD5C000051FED8 /* Low.wav in Resources */ = {isa = PBXBuildFile; fileRef = BCFCE44C28DD5C000051FED8 /* Low.wav */; };
@@ -1538,7 +1504,6 @@
 		BC12639B28FF8E6D00509E90 /* HomeRecommendMusicView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeRecommendMusicView.h; sourceTree = "<group>"; };
 		BC12639C28FF8E6D00509E90 /* HomeRecommendMusicView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeRecommendMusicView.m; sourceTree = "<group>"; };
 		BC12639E28FF8E7400509E90 /* HomeRecommendMusicView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HomeRecommendMusicView.xib; sourceTree = "<group>"; };
-		BC1553782C4E73C300F6A151 /* KSToolLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = KSToolLibrary.framework; sourceTree = "<group>"; };
 		BC1D023F2C0490AB001F6A94 /* KSMuteTipsView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = KSMuteTipsView.xib; sourceTree = "<group>"; };
 		BC1D02402C0490AB001F6A94 /* KSMuteTipsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSMuteTipsView.m; sourceTree = "<group>"; };
 		BC1D02412C0490AB001F6A94 /* KSMuteTipsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSMuteTipsView.h; sourceTree = "<group>"; };
@@ -1974,6 +1939,12 @@
 		BC84183D2AC2D96600D8F90E /* PasswordCheckBodyView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PasswordCheckBodyView.h; sourceTree = "<group>"; };
 		BC84183E2AC2D96600D8F90E /* PasswordCheckBodyView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PasswordCheckBodyView.m; sourceTree = "<group>"; };
 		BC8418402AC2D96C00D8F90E /* PasswordCheckBodyView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PasswordCheckBodyView.xib; sourceTree = "<group>"; };
+		BC85A9DD2C6B5268003C1ABE /* KSToolLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = KSToolLibrary.framework; sourceTree = "<group>"; };
+		BC85A9DE2C6B5268003C1ABE /* CloudAccompanyLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CloudAccompanyLibrary.framework; sourceTree = "<group>"; };
+		BC85A9E12C6B570E003C1ABE /* KSRealtimeAnalyzer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSRealtimeAnalyzer.h; sourceTree = "<group>"; };
+		BC85A9E22C6B570E003C1ABE /* KSRealtimeAnalyzer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSRealtimeAnalyzer.m; sourceTree = "<group>"; };
+		BC85A9E32C6B570E003C1ABE /* KSSpectrumView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSSpectrumView.h; sourceTree = "<group>"; };
+		BC85A9E42C6B570E003C1ABE /* KSSpectrumView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSSpectrumView.m; sourceTree = "<group>"; };
 		BC89AC072AB0840E00B077AF /* TenantRecommendMusicView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TenantRecommendMusicView.h; sourceTree = "<group>"; };
 		BC89AC082AB0840E00B077AF /* TenantRecommendMusicView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TenantRecommendMusicView.m; sourceTree = "<group>"; };
 		BC89AC0A2AB0841400B077AF /* TenantRecommendMusicView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TenantRecommendMusicView.xib; sourceTree = "<group>"; };
@@ -1989,57 +1960,6 @@
 		BC89AC1B2AB08FE700B077AF /* TenantMusicCellView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TenantMusicCellView.h; sourceTree = "<group>"; };
 		BC89AC1C2AB08FE700B077AF /* TenantMusicCellView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TenantMusicCellView.m; sourceTree = "<group>"; };
 		BC89AC1E2AB08FF500B077AF /* TenantMusicCellView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TenantMusicCellView.xib; sourceTree = "<group>"; };
-		BC8A4547283DC33400094BBB /* KSCloudViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSCloudViewController.h; sourceTree = "<group>"; };
-		BC8A4548283DC33400094BBB /* KSCloudViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSCloudViewController.m; sourceTree = "<group>"; };
-		BC8A4553283DC33400094BBB /* KSXMLInfoParse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSXMLInfoParse.h; sourceTree = "<group>"; };
-		BC8A4554283DC33400094BBB /* KYSourceParseManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KYSourceParseManager.m; sourceTree = "<group>"; };
-		BC8A4555283DC33400094BBB /* CloudSongMessageModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CloudSongMessageModel.h; sourceTree = "<group>"; };
-		BC8A4556283DC33400094BBB /* KSParseMessageModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSParseMessageModel.h; sourceTree = "<group>"; };
-		BC8A4557283DC33400094BBB /* TBXML.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TBXML.m; sourceTree = "<group>"; };
-		BC8A4558283DC33400094BBB /* SubjectFinger.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = SubjectFinger.plist; sourceTree = "<group>"; };
-		BC8A4559283DC33400094BBB /* CloudSongMessageModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CloudSongMessageModel.m; sourceTree = "<group>"; };
-		BC8A455A283DC33400094BBB /* KSXMLInfoParse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSXMLInfoParse.m; sourceTree = "<group>"; };
-		BC8A455B283DC33400094BBB /* KYSourceParseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KYSourceParseManager.h; sourceTree = "<group>"; };
-		BC8A455C283DC33400094BBB /* KSParseMessageModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSParseMessageModel.m; sourceTree = "<group>"; };
-		BC8A455D283DC33400094BBB /* TBXML.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TBXML.h; sourceTree = "<group>"; };
-		BC8A455E283DC33400094BBB /* FingerList.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = FingerList.plist; sourceTree = "<group>"; };
-		BC8A4561283DC33400094BBB /* SettingPageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingPageView.h; sourceTree = "<group>"; };
-		BC8A4562283DC33400094BBB /* JudgePageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JudgePageView.h; sourceTree = "<group>"; };
-		BC8A4563283DC33400094BBB /* SettingPageView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SettingPageView.xib; sourceTree = "<group>"; };
-		BC8A4564283DC33400094BBB /* JudgePageView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = JudgePageView.xib; sourceTree = "<group>"; };
-		BC8A4565283DC33400094BBB /* KSCloudSettingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSCloudSettingView.m; sourceTree = "<group>"; };
-		BC8A4566283DC33400094BBB /* SettingPageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingPageView.m; sourceTree = "<group>"; };
-		BC8A4567283DC33400094BBB /* JudgePageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JudgePageView.m; sourceTree = "<group>"; };
-		BC8A4568283DC33400094BBB /* KSCloudSettingView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = KSCloudSettingView.xib; sourceTree = "<group>"; };
-		BC8A4569283DC33400094BBB /* KSCloudSettingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSCloudSettingView.h; sourceTree = "<group>"; };
-		BC8A456B283DC33400094BBB /* ScoreAnimationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScoreAnimationView.h; sourceTree = "<group>"; };
-		BC8A456C283DC33400094BBB /* StaffImageDisplayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StaffImageDisplayView.h; sourceTree = "<group>"; };
-		BC8A456D283DC33400094BBB /* CloudControlButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CloudControlButton.h; sourceTree = "<group>"; };
-		BC8A456E283DC33400094BBB /* StaffImageDisplayView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StaffImageDisplayView.m; sourceTree = "<group>"; };
-		BC8A456F283DC33400094BBB /* ScoreAnimationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScoreAnimationView.m; sourceTree = "<group>"; };
-		BC8A4570283DC33400094BBB /* CloudControlButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CloudControlButton.m; sourceTree = "<group>"; };
-		BC8A4576283DC33400094BBB /* TrackChooseView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TrackChooseView.m; sourceTree = "<group>"; };
-		BC8A4577283DC33400094BBB /* TrackChooseView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TrackChooseView.xib; sourceTree = "<group>"; };
-		BC8A4578283DC33400094BBB /* TrackChooseView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackChooseView.h; sourceTree = "<group>"; };
-		BC8A457A283DC33400094BBB /* KSTrackingSlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSTrackingSlider.h; sourceTree = "<group>"; };
-		BC8A457B283DC33400094BBB /* KSSliderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSSliderView.m; sourceTree = "<group>"; };
-		BC8A457C283DC33400094BBB /* KSTrackingSlider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSTrackingSlider.m; sourceTree = "<group>"; };
-		BC8A457D283DC33400094BBB /* KSSliderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSSliderView.h; sourceTree = "<group>"; };
-		BC8A457F283DC33400094BBB /* SoundCheckView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SoundCheckView.m; sourceTree = "<group>"; };
-		BC8A4580283DC33400094BBB /* SoundCheckView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SoundCheckView.xib; sourceTree = "<group>"; };
-		BC8A4581283DC33400094BBB /* SoundCheckView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SoundCheckView.h; sourceTree = "<group>"; };
-		BC8A4583283DC33400094BBB /* CloudFeedbackView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CloudFeedbackView.h; sourceTree = "<group>"; };
-		BC8A4584283DC33400094BBB /* CloudHelpView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CloudHelpView.m; sourceTree = "<group>"; };
-		BC8A4585283DC33400094BBB /* CloudHelpView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CloudHelpView.xib; sourceTree = "<group>"; };
-		BC8A4586283DC33400094BBB /* CloudFeedbackView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CloudFeedbackView.m; sourceTree = "<group>"; };
-		BC8A4587283DC33400094BBB /* CloudHelpView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CloudHelpView.h; sourceTree = "<group>"; };
-		BC8A4588283DC33400094BBB /* CloudFeedbackView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CloudFeedbackView.xib; sourceTree = "<group>"; };
-		BC8A458A283DC33400094BBB /* EvaluateResultAlert.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = EvaluateResultAlert.xib; sourceTree = "<group>"; };
-		BC8A458B283DC33400094BBB /* EvaluateResultAlert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EvaluateResultAlert.h; sourceTree = "<group>"; };
-		BC8A458C283DC33400094BBB /* NoWiredTipsAlert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoWiredTipsAlert.h; sourceTree = "<group>"; };
-		BC8A458D283DC33400094BBB /* EvaluateResultAlert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EvaluateResultAlert.m; sourceTree = "<group>"; };
-		BC8A458E283DC33400094BBB /* NoWiredTipsAlert.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NoWiredTipsAlert.xib; sourceTree = "<group>"; };
-		BC8A458F283DC33400094BBB /* NoWiredTipsAlert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NoWiredTipsAlert.m; sourceTree = "<group>"; };
 		BC8A45C0283DDD7100094BBB /* synthgms.sf2 */ = {isa = PBXFileReference; lastKnownFileType = file; path = synthgms.sf2; sourceTree = "<group>"; };
 		BC8A45C2283DDE5C00094BBB /* CoreMIDI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMIDI.framework; path = System/Library/Frameworks/CoreMIDI.framework; sourceTree = SDKROOT; };
 		BC8A45C4283DDE6D00094BBB /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
@@ -2094,14 +2014,6 @@
 		BC9AA0DA2ABC434900CD954D /* KSCustomLoadingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSCustomLoadingView.m; sourceTree = "<group>"; };
 		BC9AA0DB2ABC434900CD954D /* KSCustomLoadingView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = KSCustomLoadingView.xib; sourceTree = "<group>"; };
 		BC9AA0DC2ABC434900CD954D /* KSHudLoagingManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSHudLoagingManager.h; sourceTree = "<group>"; };
-		BCA1135A28A3A2BB007FAFB9 /* bass.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = bass.txt; sourceTree = "<group>"; };
-		BCA1135B28A3A2BB007FAFB9 /* bass.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = bass.xcframework; sourceTree = "<group>"; };
-		BCA1135C28A3A2BB007FAFB9 /* bass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bass.h; sourceTree = "<group>"; };
-		BCA1135F28A3A2D0007FAFB9 /* bassmidi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bassmidi.h; sourceTree = "<group>"; };
-		BCA1136028A3A2D0007FAFB9 /* bassmidi.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = bassmidi.txt; sourceTree = "<group>"; };
-		BCA1136128A3A2D0007FAFB9 /* bassmidi.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = bassmidi.xcframework; sourceTree = "<group>"; };
-		BCA1136428A3A2EA007FAFB9 /* BassMidiEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BassMidiEngine.h; path = KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/BassMidiEngine.h; sourceTree = SOURCE_ROOT; };
-		BCA1136528A3A2EA007FAFB9 /* BassMidiEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BassMidiEngine.m; path = KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/BassMidiEngine.m; sourceTree = SOURCE_ROOT; };
 		BCA1136728A3A5CF007FAFB9 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
 		BCA193B6282B6094004A585D /* RecentCourseModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecentCourseModel.h; sourceTree = "<group>"; };
 		BCA193B7282B6094004A585D /* RecentCourseModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RecentCourseModel.m; sourceTree = "<group>"; };
@@ -2489,7 +2401,6 @@
 		BCF880DD2B91C4FA0007B8F0 /* Config-debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Config-debug.xcconfig"; sourceTree = "<group>"; };
 		BCF880DF2B91C5090007B8F0 /* Config-test.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Config-test.xcconfig"; sourceTree = "<group>"; };
 		BCF880E02B91C5150007B8F0 /* Config-release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Config-release.xcconfig"; sourceTree = "<group>"; };
-		BCFC09C92C47F6FF009A727F /* CloudAccompanyLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CloudAccompanyLibrary.framework; sourceTree = "<group>"; };
 		BCFC09CF2C48B3D7009A727F /* KSAccompanyDraftViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KSAccompanyDraftViewController.h; sourceTree = "<group>"; };
 		BCFC09D02C48B3D7009A727F /* KSAccompanyDraftViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KSAccompanyDraftViewController.m; sourceTree = "<group>"; };
 		BCFC09D82C48C8DD009A727F /* UserVip.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UserVip.m; sourceTree = "<group>"; };
@@ -2573,9 +2484,9 @@
 			files = (
 				BCA1136828A3A5CF007FAFB9 /* Accelerate.framework in Frameworks */,
 				BCFEE1932AD15C0E000E888F /* SoundpipeAudioKit in Frameworks */,
-				BCFC09CA2C47F6FF009A727F /* CloudAccompanyLibrary.framework in Frameworks */,
+				BC85A9E02C6B5268003C1ABE /* CloudAccompanyLibrary.framework in Frameworks */,
 				BCFEE18D2AD15BD4000E888F /* AudioKitEX in Frameworks */,
-				BC1553792C4E73C300F6A151 /* KSToolLibrary.framework in Frameworks */,
+				BC85A9DF2C6B5268003C1ABE /* KSToolLibrary.framework in Frameworks */,
 				BC8B6E152856E20800866917 /* WebKit.framework in Frameworks */,
 				BC8A45CB283DDEA100094BBB /* AVFoundation.framework in Frameworks */,
 				BCD9294F28F8FCA4006793E4 /* AudioKit in Frameworks */,
@@ -2585,7 +2496,6 @@
 				BC71D0F52881A2420010F14B /* UMAPM.framework in Frameworks */,
 				BC71D0F72881A2420010F14B /* UMCommon.framework in Frameworks */,
 				BC8A45C9283DDE9A00094BBB /* CoreMedia.framework in Frameworks */,
-				BCA1135E28A3A2BB007FAFB9 /* bass.xcframework in Frameworks */,
 				BC71D1012881A2420010F14B /* libSocialSina.a in Frameworks */,
 				BC71D1062881A2420010F14B /* TencentOpenAPI.framework in Frameworks */,
 				BC8B6E132856E1F600866917 /* CoreTelephony.framework in Frameworks */,
@@ -2593,7 +2503,6 @@
 				BC71D1032881A2420010F14B /* libWeiboSDK.a in Frameworks */,
 				BC8A45C7283DDE8E00094BBB /* VideoToolbox.framework in Frameworks */,
 				BC3A556E2BAA7B2D002E1616 /* KSTunerLibrary.framework in Frameworks */,
-				BCA1136328A3A2D0007FAFB9 /* bassmidi.xcframework in Frameworks */,
 				BC8B6E172856E21000866917 /* SystemConfiguration.framework in Frameworks */,
 				BC71D0FE2881A2420010F14B /* libSocialOfficialWeChat.a in Frameworks */,
 				BC71D1002881A2420010F14B /* libWeChatSDK.a in Frameworks */,
@@ -2861,7 +2770,6 @@
 				BC106BBE2A933688000759A9 /* TXLive */,
 				BCC0F5E52A8CD7A600C4EFA4 /* TXClassRoom */,
 				BC71D1342887CD470010F14B /* AnimationLaunch */,
-				BC8A4545283DC33400094BBB /* CloudEngine */,
 				BCB6340A27F6D29500ACFDCF /* Live */,
 				275FA1F127E7356A00CFEA2E /* Home */,
 				275FA1F727E7356A00CFEA2E /* Course */,
@@ -4454,6 +4362,7 @@
 		BC38C3D42AF893B300ABFCC2 /* AudioMerge */ = {
 			isa = PBXGroup;
 			children = (
+				BC85A9E52C6B570E003C1ABE /* MergeAudioAnimation */,
 				BCED0AF62C4651F800369AED /* MergePlayer */,
 				BC38C3DE2AF893B300ABFCC2 /* AudioPlayAnimationView */,
 				BC38C3D62AF893B300ABFCC2 /* KSAudioAnimationView.h */,
@@ -4671,9 +4580,9 @@
 			children = (
 				BC00A65F2BB58FDB00231B74 /* LLPhotoBrowse.bundle */,
 				BC00A6602BB58FDC00231B74 /* WMPlayer.bundle */,
-				BC1553782C4E73C300F6A151 /* KSToolLibrary.framework */,
 				BC3A55682BAA7B19002E1616 /* KSTunerLibrary.framework */,
-				BCFC09C92C47F6FF009A727F /* CloudAccompanyLibrary.framework */,
+				BC85A9DD2C6B5268003C1ABE /* KSToolLibrary.framework */,
+				BC85A9DE2C6B5268003C1ABE /* CloudAccompanyLibrary.framework */,
 				BC3BF62F2B9EAFC800831494 /* client.p12 */,
 			);
 			path = ToolKit;
@@ -5165,6 +5074,17 @@
 			path = HotLiveCourse;
 			sourceTree = "<group>";
 		};
+		BC85A9E52C6B570E003C1ABE /* MergeAudioAnimation */ = {
+			isa = PBXGroup;
+			children = (
+				BC85A9E12C6B570E003C1ABE /* KSRealtimeAnalyzer.h */,
+				BC85A9E22C6B570E003C1ABE /* KSRealtimeAnalyzer.m */,
+				BC85A9E32C6B570E003C1ABE /* KSSpectrumView.h */,
+				BC85A9E42C6B570E003C1ABE /* KSSpectrumView.m */,
+			);
+			path = MergeAudioAnimation;
+			sourceTree = "<group>";
+		};
 		BC89AC042AB083F500B077AF /* HotMusic */ = {
 			isa = PBXGroup;
 			children = (
@@ -5195,161 +5115,6 @@
 			path = RecommendMusic;
 			sourceTree = "<group>";
 		};
-		BC8A4545283DC33400094BBB /* CloudEngine */ = {
-			isa = PBXGroup;
-			children = (
-				BC8A4546283DC33400094BBB /* Controller */,
-				BC8A4552283DC33400094BBB /* Model */,
-				BC8A455F283DC33400094BBB /* View */,
-				BC8A4590283DC33400094BBB /* BASSMidiPlayer */,
-			);
-			path = CloudEngine;
-			sourceTree = "<group>";
-		};
-		BC8A4546283DC33400094BBB /* Controller */ = {
-			isa = PBXGroup;
-			children = (
-				BC8A4547283DC33400094BBB /* KSCloudViewController.h */,
-				BC8A4548283DC33400094BBB /* KSCloudViewController.m */,
-			);
-			path = Controller;
-			sourceTree = "<group>";
-		};
-		BC8A4552283DC33400094BBB /* Model */ = {
-			isa = PBXGroup;
-			children = (
-				BC8A4553283DC33400094BBB /* KSXMLInfoParse.h */,
-				BC8A4554283DC33400094BBB /* KYSourceParseManager.m */,
-				BC8A4555283DC33400094BBB /* CloudSongMessageModel.h */,
-				BC8A4556283DC33400094BBB /* KSParseMessageModel.h */,
-				BC8A4557283DC33400094BBB /* TBXML.m */,
-				BC8A4558283DC33400094BBB /* SubjectFinger.plist */,
-				BC8A4559283DC33400094BBB /* CloudSongMessageModel.m */,
-				BC8A455A283DC33400094BBB /* KSXMLInfoParse.m */,
-				BC8A455B283DC33400094BBB /* KYSourceParseManager.h */,
-				BC8A455C283DC33400094BBB /* KSParseMessageModel.m */,
-				BC8A455D283DC33400094BBB /* TBXML.h */,
-				BC8A455E283DC33400094BBB /* FingerList.plist */,
-			);
-			path = Model;
-			sourceTree = "<group>";
-		};
-		BC8A455F283DC33400094BBB /* View */ = {
-			isa = PBXGroup;
-			children = (
-				BC8A4571283DC33400094BBB /* beat */,
-				BC8A4575283DC33400094BBB /* Channel */,
-				BC8A4582283DC33400094BBB /* Help */,
-				BC8A4560283DC33400094BBB /* SettingView */,
-				BC8A457E283DC33400094BBB /* SoundCheckView */,
-				BC8A4579283DC33400094BBB /* SpeedSlider */,
-				BC8A456A283DC33400094BBB /* StaffView */,
-				BC8A4589283DC33400094BBB /* TipsAlert */,
-			);
-			path = View;
-			sourceTree = "<group>";
-		};
-		BC8A4560283DC33400094BBB /* SettingView */ = {
-			isa = PBXGroup;
-			children = (
-				BC8A4561283DC33400094BBB /* SettingPageView.h */,
-				BC8A4562283DC33400094BBB /* JudgePageView.h */,
-				BC8A4563283DC33400094BBB /* SettingPageView.xib */,
-				BC8A4564283DC33400094BBB /* JudgePageView.xib */,
-				BC8A4565283DC33400094BBB /* KSCloudSettingView.m */,
-				BC8A4566283DC33400094BBB /* SettingPageView.m */,
-				BC8A4567283DC33400094BBB /* JudgePageView.m */,
-				BC8A4568283DC33400094BBB /* KSCloudSettingView.xib */,
-				BC8A4569283DC33400094BBB /* KSCloudSettingView.h */,
-			);
-			path = SettingView;
-			sourceTree = "<group>";
-		};
-		BC8A456A283DC33400094BBB /* StaffView */ = {
-			isa = PBXGroup;
-			children = (
-				BC8A456D283DC33400094BBB /* CloudControlButton.h */,
-				BC8A4570283DC33400094BBB /* CloudControlButton.m */,
-				BC8A456B283DC33400094BBB /* ScoreAnimationView.h */,
-				BC8A456F283DC33400094BBB /* ScoreAnimationView.m */,
-				BC8A456C283DC33400094BBB /* StaffImageDisplayView.h */,
-				BC8A456E283DC33400094BBB /* StaffImageDisplayView.m */,
-			);
-			path = StaffView;
-			sourceTree = "<group>";
-		};
-		BC8A4571283DC33400094BBB /* beat */ = {
-			isa = PBXGroup;
-			children = (
-			);
-			path = beat;
-			sourceTree = "<group>";
-		};
-		BC8A4575283DC33400094BBB /* Channel */ = {
-			isa = PBXGroup;
-			children = (
-				BC8A4576283DC33400094BBB /* TrackChooseView.m */,
-				BC8A4577283DC33400094BBB /* TrackChooseView.xib */,
-				BC8A4578283DC33400094BBB /* TrackChooseView.h */,
-			);
-			path = Channel;
-			sourceTree = "<group>";
-		};
-		BC8A4579283DC33400094BBB /* SpeedSlider */ = {
-			isa = PBXGroup;
-			children = (
-				BC8A457D283DC33400094BBB /* KSSliderView.h */,
-				BC8A457B283DC33400094BBB /* KSSliderView.m */,
-				BC8A457A283DC33400094BBB /* KSTrackingSlider.h */,
-				BC8A457C283DC33400094BBB /* KSTrackingSlider.m */,
-			);
-			path = SpeedSlider;
-			sourceTree = "<group>";
-		};
-		BC8A457E283DC33400094BBB /* SoundCheckView */ = {
-			isa = PBXGroup;
-			children = (
-				BC8A457F283DC33400094BBB /* SoundCheckView.m */,
-				BC8A4580283DC33400094BBB /* SoundCheckView.xib */,
-				BC8A4581283DC33400094BBB /* SoundCheckView.h */,
-			);
-			path = SoundCheckView;
-			sourceTree = "<group>";
-		};
-		BC8A4582283DC33400094BBB /* Help */ = {
-			isa = PBXGroup;
-			children = (
-				BC8A4583283DC33400094BBB /* CloudFeedbackView.h */,
-				BC8A4584283DC33400094BBB /* CloudHelpView.m */,
-				BC8A4585283DC33400094BBB /* CloudHelpView.xib */,
-				BC8A4586283DC33400094BBB /* CloudFeedbackView.m */,
-				BC8A4587283DC33400094BBB /* CloudHelpView.h */,
-				BC8A4588283DC33400094BBB /* CloudFeedbackView.xib */,
-			);
-			path = Help;
-			sourceTree = "<group>";
-		};
-		BC8A4589283DC33400094BBB /* TipsAlert */ = {
-			isa = PBXGroup;
-			children = (
-				BC8A458A283DC33400094BBB /* EvaluateResultAlert.xib */,
-				BC8A458B283DC33400094BBB /* EvaluateResultAlert.h */,
-				BC8A458C283DC33400094BBB /* NoWiredTipsAlert.h */,
-				BC8A458D283DC33400094BBB /* EvaluateResultAlert.m */,
-				BC8A458E283DC33400094BBB /* NoWiredTipsAlert.xib */,
-				BC8A458F283DC33400094BBB /* NoWiredTipsAlert.m */,
-			);
-			path = TipsAlert;
-			sourceTree = "<group>";
-		};
-		BC8A4590283DC33400094BBB /* BASSMidiPlayer */ = {
-			isa = PBXGroup;
-			children = (
-				BCA1135928A3A2B5007FAFB9 /* Source */,
-			);
-			path = BASSMidiPlayer;
-			sourceTree = "<group>";
-		};
 		BC8A45BF283DDD7100094BBB /* SoundFontFile */ = {
 			isa = PBXGroup;
 			children = (
@@ -5456,21 +5221,6 @@
 			path = LoadingManager;
 			sourceTree = "<group>";
 		};
-		BCA1135928A3A2B5007FAFB9 /* Source */ = {
-			isa = PBXGroup;
-			children = (
-				BCA1136428A3A2EA007FAFB9 /* BassMidiEngine.h */,
-				BCA1136528A3A2EA007FAFB9 /* BassMidiEngine.m */,
-				BCA1135F28A3A2D0007FAFB9 /* bassmidi.h */,
-				BCA1136028A3A2D0007FAFB9 /* bassmidi.txt */,
-				BCA1136128A3A2D0007FAFB9 /* bassmidi.xcframework */,
-				BCA1135C28A3A2BB007FAFB9 /* bass.h */,
-				BCA1135A28A3A2BB007FAFB9 /* bass.txt */,
-				BCA1135B28A3A2BB007FAFB9 /* bass.xcframework */,
-			);
-			path = Source;
-			sourceTree = "<group>";
-		};
 		BCB6340A27F6D29500ACFDCF /* Live */ = {
 			isa = PBXGroup;
 			children = (
@@ -6440,7 +6190,6 @@
 				BC106C3B2A9338A7000759A9 /* custom_loading.json in Resources */,
 				BC89AC1A2AB08FA100B077AF /* TenantMusicCollectionViewCell.xib in Resources */,
 				2723B63227F157D500E0B90B /* GroupSettingBodyView.xib in Resources */,
-				BCA1136228A3A2D0007FAFB9 /* bassmidi.txt in Resources */,
 				BCC0F65C2A8CD8F500C4EFA4 /* TxClassroomChatMineCell.xib in Resources */,
 				BC71D272288804CD0010F14B /* img_27.png in Resources */,
 				BCFE53F728128A9600AD6786 /* TeacherShowCell.xib in Resources */,
@@ -6480,7 +6229,6 @@
 				BCC583C028A9EC6400BAB4CF /* cloud_animation_15.png in Resources */,
 				BC119280280FB10900A716F7 /* AccompanyRemarkCell.xib in Resources */,
 				BCC409012AFCE6B500C60249 /* MusicPublicContentView.xib in Resources */,
-				BC8A45B6283DC33400094BBB /* NoWiredTipsAlert.xib in Resources */,
 				BC71D271288804CD0010F14B /* img_26.png in Resources */,
 				BC12639F28FF8E7400509E90 /* HomeRecommendMusicView.xib in Resources */,
 				BC00A6622BB58FDC00231B74 /* WMPlayer.bundle in Resources */,
@@ -6490,7 +6238,6 @@
 				BC11925A280FA85300A716F7 /* HomeworkSortView.xib in Resources */,
 				2723B62527F157D500E0B90B /* GroupNoticeCell.xib in Resources */,
 				BCC583D228A9EC6400BAB4CF /* cloud_animation.json in Resources */,
-				BC8A459E283DC33400094BBB /* FingerList.plist in Resources */,
 				275FA23D27E7356B00CFEA2E /* PasswordBodyView.xib in Resources */,
 				BC5367C4283F6D58008428E8 /* HomeLiveCourseView.xib in Resources */,
 				BC2DFF5D28C097DC0056105A /* styleAnimation.json in Resources */,
@@ -6524,7 +6271,6 @@
 				BCBFDF5228115DA40052AFE5 /* HomeIntroduceView.xib in Resources */,
 				BC71D277288804CD0010F14B /* img_36.png in Resources */,
 				BC71D250288804CD0010F14B /* img_6.png in Resources */,
-				BC8A45AF283DC33400094BBB /* SoundCheckView.xib in Resources */,
 				BCFDA63828BCA1C60022B497 /* HomeRecentCourseView.xib in Resources */,
 				BC119270280FAF7D00A716F7 /* AccompanyCourseInfoCell.xib in Resources */,
 				BC2DFF5828BE143A0056105A /* HomeTempLiveCell.xib in Resources */,
@@ -6542,7 +6288,6 @@
 				BC106C4C2A933E75000759A9 /* LiveRoomHeadView.xib in Resources */,
 				BCC583CF28A9EC6400BAB4CF /* cloud_animation_1.png in Resources */,
 				2723B5C427F157B100E0B90B /* KSChatListSearchView.xib in Resources */,
-				BC8A459A283DC33400094BBB /* SubjectFinger.plist in Resources */,
 				BC71D275288804CD0010F14B /* img_23.png in Resources */,
 				BC71D0F82881A2420010F14B /* iOS集成升级必读.pdf in Resources */,
 				BCC583CC28A9EC6400BAB4CF /* cloud_animation_5.png in Resources */,
@@ -6592,7 +6337,6 @@
 				BC42CAA42BEC8272001F076E /* RhythmView.xib in Resources */,
 				BC9AA0B72ABC1C2A00CD954D /* GroupQuitAlert.xib in Resources */,
 				BCB6348127F6D29600ACFDCF /* LiveSeatApplyCell.xib in Resources */,
-				BC8A45A4283DC33400094BBB /* KSCloudSettingView.xib in Resources */,
 				BC38C4602AFA095D00ABFCC2 /* MineWorksBottomView.xib in Resources */,
 				2723B62D27F157D500E0B90B /* GroupApplyMemberCell.xib in Resources */,
 				BCC0F6702A8CD8F500C4EFA4 /* MainToolButton.xib in Resources */,
@@ -6621,7 +6365,6 @@
 				BC27A076280FF61300F91E27 /* AccompanyDetailBottomView.xib in Resources */,
 				BCBFDF4D28115C7A0052AFE5 /* HomeHotCourseView.xib in Resources */,
 				BC71D2892888083B0010F14B /* tabbar5.json in Resources */,
-				BC8A45B4283DC33400094BBB /* EvaluateResultAlert.xib in Resources */,
 				BCC0F6B12A8CDD4000C4EFA4 /* class_stop.mp3 in Resources */,
 				BCBFDF3928110C6F0052AFE5 /* HomeNavView.xib in Resources */,
 				BC89AC0B2AB0841400B077AF /* TenantRecommendMusicView.xib in Resources */,
@@ -6650,7 +6393,6 @@
 				BC27A070280FF56C00F91E27 /* AccompanyStudentEvaCell.xib in Resources */,
 				2723B63927F157D500E0B90B /* GroupMemberListCell.xib in Resources */,
 				BCFCE44E28DD5C000051FED8 /* Low.wav in Resources */,
-				BC8A45A0283DC33400094BBB /* JudgePageView.xib in Resources */,
 				BC802D9428B897670079E350 /* LiveApplyingView.xib in Resources */,
 				BC71D244288804CD0010F14B /* img_10.png in Resources */,
 				BC0212F827FC4A080040569F /* SubjectImageCell.xib in Resources */,
@@ -6677,7 +6419,6 @@
 				BC119217280ED6A900A716F7 /* MyLessonSearchView.xib in Resources */,
 				BCC583BD28A9EC6400BAB4CF /* cloud_animation_25.png in Resources */,
 				BCC583BC28A9EC6400BAB4CF /* cloud_animation_19.png in Resources */,
-				BC8A459F283DC33400094BBB /* SettingPageView.xib in Resources */,
 				BC71D262288804CD0010F14B /* img_54.png in Resources */,
 				BC8C2C5A2823F57100FBA5D5 /* areainfo.json in Resources */,
 				BCFDA64E28BCA2000022B497 /* musicRoom_animation_3.png in Resources */,
@@ -6691,7 +6432,6 @@
 				BC71D24E288804CD0010F14B /* img_16.png in Resources */,
 				27F9033727E87C8B00C08A19 /* MineNavView.xib in Resources */,
 				BC38C4A32AFA4F6C00ABFCC2 /* TenantMineFunctionView.xib in Resources */,
-				BC8A45AB283DC33400094BBB /* TrackChooseView.xib in Resources */,
 				BCC0F6B32A8CDD4000C4EFA4 /* low_staff.png in Resources */,
 				BCB9FA47286EDCD7005D766B /* KSTipsAlert.xib in Resources */,
 				BCFDA64C28BCA2000022B497 /* live_animation_0.png in Resources */,
@@ -6715,11 +6455,9 @@
 				BC756CC828FE867000AA9ECB /* UserDetailBottomView.xib in Resources */,
 				BCFDA62628BC94480022B497 /* HomeNavSearchView.xib in Resources */,
 				BC71D0F42881A2420010F14B /* UMCommonLog.bundle in Resources */,
-				BCA1135D28A3A2BB007FAFB9 /* bass.txt in Resources */,
 				BC8A45C1283DDD7100094BBB /* synthgms.sf2 in Resources */,
 				BC71D24B288804CD0010F14B /* img_2.png in Resources */,
 				BC0D1F72281015B000C5D9E5 /* VideoCourseCell.xib in Resources */,
-				BC8A45B1283DC33400094BBB /* CloudHelpView.xib in Resources */,
 				BCECE24A2B3D670500C0D555 /* FeedbackSortView.xib in Resources */,
 				BCFDA64A28BCA2000022B497 /* accomapny_animation.json in Resources */,
 				BCECE2492B3D670500C0D555 /* FeedbackNavView.xib in Resources */,
@@ -6735,7 +6473,6 @@
 				BCCE95C92AB0363100AB6385 /* TenantDarkSearhView.xib in Resources */,
 				BC40B9FF281177BD00DEC0D1 /* HomeInformationCell.xib in Resources */,
 				BC31BF2E2B21925700F7D538 /* WidgetDotView.xib in Resources */,
-				BC8A45B3283DC33400094BBB /* CloudFeedbackView.xib in Resources */,
 				BCFDA65228BCA2000022B497 /* musicRoom_animation_0.png in Resources */,
 				BCC0F66B2A8CD8F500C4EFA4 /* ClassRoomTitleButton.xib in Resources */,
 				BC31BF1B2B21925700F7D538 /* TuningNavView.xib in Resources */,
@@ -6932,7 +6669,6 @@
 				BCB6347727F6D29600ACFDCF /* LiveRoomLikeLayer.m in Sources */,
 				BCC0F6532A8CD8F500C4EFA4 /* TXClassroomVideoListView.m in Sources */,
 				BC40B9F82811767A00DEC0D1 /* HotInformationHeadView.m in Sources */,
-				BC8A45AD283DC33400094BBB /* KSTrackingSlider.m in Sources */,
 				BC7663152827E49900C91A1D /* NotiferHeadView.m in Sources */,
 				2723B67F27F15D3D00E0B90B /* AboutUsViewController.m in Sources */,
 				2779356127E324A70010E277 /* KSAudioRecordManager.m in Sources */,
@@ -6943,7 +6679,6 @@
 				BC38C3EC2AF893B400ABFCC2 /* KSAudioPlayAnimationView.m in Sources */,
 				BCECE24E2B3D670500C0D555 /* CourseFileDisplayView.m in Sources */,
 				BCCE95CC2AB03BE200AB6385 /* TenantDragView.m in Sources */,
-				BC8A459C283DC33400094BBB /* KSXMLInfoParse.m in Sources */,
 				BC31BF2A2B21925700F7D538 /* WidgetBottomButtonView.m in Sources */,
 				BC106C392A9338A7000759A9 /* TXLiveVideoView.m in Sources */,
 				2779356527E324A70010E277 /* KSMediaManager.m in Sources */,
@@ -6960,16 +6695,13 @@
 				BC0078712BCD17ED0076CD22 /* GroupAlbumModel.m in Sources */,
 				BC43CAC92A88C9570011EB5D /* KSTXGroupChatViewController.m in Sources */,
 				275FA1DA27E7351900CFEA2E /* KSNetworkingManager.m in Sources */,
-				BC8A45B0283DC33400094BBB /* CloudHelpView.m in Sources */,
 				BCC0F6B62A8CDD4000C4EFA4 /* LocalRenderManager.m in Sources */,
 				BC106C042A933829000759A9 /* TXLiveMessageMemberUp.m in Sources */,
 				BCC0F6542A8CD8F500C4EFA4 /* TXChatBottomView.m in Sources */,
 				BCFC09DA2C48C8DE009A727F /* UserVip.m in Sources */,
 				BC02381928685087005560CA /* LiveAnimationView.m in Sources */,
 				BCC0F6122A8CD89400C4EFA4 /* TXClassroomViewController.m in Sources */,
-				BC8A45AA283DC33400094BBB /* TrackChooseView.m in Sources */,
 				BC106C3A2A9338A7000759A9 /* TXSeatContainerView.m in Sources */,
-				BC8A45B2283DC33400094BBB /* CloudFeedbackView.m in Sources */,
 				BC31BF322B21925700F7D538 /* WidgetSpeedView.m in Sources */,
 				BCC409062AFCE6B500C60249 /* VideoCropImageViewCell.m in Sources */,
 				BC60E3CD287D552800B05441 /* DeleteAccountBodyView.m in Sources */,
@@ -7005,10 +6737,10 @@
 				BCECE2552B3D670500C0D555 /* FeedbackNavView.m in Sources */,
 				BCC0F6042A8CD86C00C4EFA4 /* TXRTCService.m in Sources */,
 				BCB6347327F6D29600ACFDCF /* KSChatEmojiCollectionCell.m in Sources */,
-				BC8A4593283DC33400094BBB /* KSCloudViewController.m in Sources */,
 				BCFDA65C28BCAEB10022B497 /* HomePageBodyView.m in Sources */,
 				2723B62327F157D500E0B90B /* LFPopupMenuDefaultConfig.m in Sources */,
 				BC31BF2F2B21925700F7D538 /* IACircularSliderTrackLayer.m in Sources */,
+				BC85A9E62C6B570E003C1ABE /* KSRealtimeAnalyzer.m in Sources */,
 				BCB9091728530E9C00F5FF69 /* KSShopCardView.m in Sources */,
 				BCCDB4332AB1C03A003C8E5F /* TenantTicketAlert.m in Sources */,
 				BC27A071280FF56C00F91E27 /* AccompanyEvaluateCell.m in Sources */,
@@ -7059,11 +6791,9 @@
 				BC40BA1B281251ED00DEC0D1 /* HomeMessageModel.m in Sources */,
 				277935BD27E324A90010E277 /* FSCalendarConstants.m in Sources */,
 				BCB6347027F6D29600ACFDCF /* LiveSeatMember.m in Sources */,
-				BC8A45AC283DC33400094BBB /* KSSliderView.m in Sources */,
 				2723B62927F157D500E0B90B /* KSChatComplainController.m in Sources */,
 				BC2933002AAEFC810024D98E /* INSSettingViewController.m in Sources */,
 				BCB5B2D12ABAFE8E005BF25D /* HomeMusicSheetLayout.m in Sources */,
-				BC8A4599283DC33400094BBB /* TBXML.m in Sources */,
 				BC31BF0D2B21925700F7D538 /* WidgetViewController.m in Sources */,
 				BC542E4B28409E9F00633781 /* InstrumentChooseViewController.m in Sources */,
 				BC9AA0DE2ABC434900CD954D /* KSCustomLoadingView.m in Sources */,
@@ -7073,7 +6803,6 @@
 				BC38C3F82AF8B3E000ABFCC2 /* KSNewAlertView.m in Sources */,
 				275FA23527E7356B00CFEA2E /* UserInfoManager.m in Sources */,
 				BC106C132A933829000759A9 /* TXControlMemberMic.m in Sources */,
-				BC8A45AE283DC33400094BBB /* SoundCheckView.m in Sources */,
 				BC71D13A2887CEB70010F14B /* LaunchAnimationViewController.m in Sources */,
 				2723B67E27F15D3D00E0B90B /* ModifyPhoneCheckController.m in Sources */,
 				BC542E5D2840A60100633781 /* UserSettingViewController.m in Sources */,
@@ -7082,15 +6811,12 @@
 				BC31BF262B21925700F7D538 /* WMGaugeView.m in Sources */,
 				BCB9FA35286D7C2F005D766B /* GuideListView.m in Sources */,
 				BCC0F60E2A8CD86C00C4EFA4 /* TXSongSyncMessage.m in Sources */,
-				BC8A45A3283DC33400094BBB /* JudgePageView.m in Sources */,
 				2779355E27E324A70010E277 /* KSAudioRecordFileManager.m in Sources */,
 				BC119234280ED97C00A716F7 /* CourseForLiveCell.m in Sources */,
 				BC106C382A9338A7000759A9 /* LiveRoomConfirmAlert.m in Sources */,
 				BCFE53E72812765600AD6786 /* HomeHotAlbumCell.m in Sources */,
 				BC1D02432C0490AB001F6A94 /* KSMuteTipsView.m in Sources */,
 				BC89AC092AB0840E00B077AF /* TenantRecommendMusicView.m in Sources */,
-				BC8A459B283DC33400094BBB /* CloudSongMessageModel.m in Sources */,
-				BC8A45B7283DC33500094BBB /* NoWiredTipsAlert.m in Sources */,
 				BCC0F6722A8CD8F500C4EFA4 /* MainToolButton.m in Sources */,
 				277935B427E324A90010E277 /* FSCalendarDelegationProxy.m in Sources */,
 				BCC0F6CA2A8CDDFE00C4EFA4 /* ClassroomService.m in Sources */,
@@ -7180,7 +6906,6 @@
 				BC43CACB2A88C9570011EB5D /* KSTXBaseChatViewController.m in Sources */,
 				BC542E612840A60E00633781 /* UseBodyView.m in Sources */,
 				BCC0F6C22A8CDDEB00C4EFA4 /* Whiteboard.m in Sources */,
-				BC8A45A6283DC33400094BBB /* ScoreAnimationView.m in Sources */,
 				BCFC09D12C48B3D7009A727F /* KSAccompanyDraftViewController.m in Sources */,
 				BC2DFF4E28BE068D0056105A /* TeacherStyleFlowLayout.m in Sources */,
 				BC38C4582AFA095D00ABFCC2 /* MineWorksOpenDisplayCell.m in Sources */,
@@ -7193,7 +6918,6 @@
 				BCCE95ED2AB05ECB00AB6385 /* TenantHotAlbumView.m in Sources */,
 				275FA1E827E7351900CFEA2E /* CustomNavViewController.m in Sources */,
 				BCCE95C72AB0362A00AB6385 /* TenantDarkSearhView.m in Sources */,
-				BC8A45B5283DC33400094BBB /* EvaluateResultAlert.m in Sources */,
 				275FA24327E73DF600CFEA2E /* InstrumentDescView.m in Sources */,
 				BC28887C2A8102890064B773 /* KSConversationListController.m in Sources */,
 				275FA1ED27E7351900CFEA2E /* KSUpdateManager.m in Sources */,
@@ -7291,10 +7015,10 @@
 				BCC0F6642A8CD8F500C4EFA4 /* TXDanBottomView.m in Sources */,
 				BC119259280FA85300A716F7 /* HomeworkListCell.m in Sources */,
 				BC38C45E2AFA095D00ABFCC2 /* MineWorksBodyView.m in Sources */,
-				BCA1136628A3A2EA007FAFB9 /* BassMidiEngine.m in Sources */,
 				BCC0F6592A8CD8F500C4EFA4 /* TXChatAreaView.m in Sources */,
 				2723B5CD27F157BE00E0B90B /* GroupListModel.m in Sources */,
 				2723B63327F157D500E0B90B /* ChatComplainBodyView.m in Sources */,
+				BC85A9E72C6B570E003C1ABE /* KSSpectrumView.m in Sources */,
 				2779357927E324A70010E277 /* KSImageButton.m in Sources */,
 				BCC0F6E52A8CE24400C4EFA4 /* KSNewWhiteBoard.m in Sources */,
 				BCD959CC28DB0BAB00B70314 /* KSImageShareViewController.m in Sources */,
@@ -7312,7 +7036,6 @@
 				BC2888752A8101C80064B773 /* KSSearchResultListController.m in Sources */,
 				2723B66D27F15CFC00E0B90B /* ModifyNameBodyView.m in Sources */,
 				BC0D95262AC2AA0900E54D3F /* NewPwdModifyViewController.m in Sources */,
-				BC8A459D283DC33400094BBB /* KSParseMessageModel.m in Sources */,
 				BC31BF242B21925700F7D538 /* WMGaugeViewStyleFlatThin.m in Sources */,
 				BC9AA0BA2ABC288000CD954D /* ChatComplainBottomView.m in Sources */,
 				275FA23327E7356B00CFEA2E /* VefiCodeLoginController.m in Sources */,
@@ -7366,10 +7089,8 @@
 				BCC0F6712A8CD8F500C4EFA4 /* TXMainToolView.m in Sources */,
 				BC38C3F02AF893B400ABFCC2 /* KSMergeAudioControlView.m in Sources */,
 				BC7663172827E49900C91A1D /* NotiferMessageCell.m in Sources */,
-				BC8A45A7283DC33400094BBB /* CloudControlButton.m in Sources */,
 				BCC0F6C32A8CDDEB00C4EFA4 /* RoomMember.m in Sources */,
 				BC60E3D3287D592800B05441 /* KSPublicAlertView.m in Sources */,
-				BC8A4598283DC33400094BBB /* KYSourceParseManager.m in Sources */,
 				2779353527E324A60010E277 /* NSObject+ReadDocument.m in Sources */,
 				BC9AA0DD2ABC434900CD954D /* KSHudLoagingManager.m in Sources */,
 				2723B63427F157D500E0B90B /* GroupApplyMemberCell.m in Sources */,
@@ -7393,12 +7114,10 @@
 				BC802D9728BC4FC40079E350 /* HomeHotMusicView.m in Sources */,
 				275FA1E527E7351900CFEA2E /* KSAccompanyWebViewController.m in Sources */,
 				BC756CB628FE4E5D00AA9ECB /* KSChatTagView.m in Sources */,
-				BC8A45A5283DC33400094BBB /* StaffImageDisplayView.m in Sources */,
 				BC11923A280ED98E00A716F7 /* AccompanyCourseCell.m in Sources */,
 				BCFDA62F28BC99410022B497 /* HomeBannerView.m in Sources */,
 				BC119264280FA90100A716F7 /* HomeworkListModel.m in Sources */,
 				2723B5A327F1578300E0B90B /* KSChatListViewController.m in Sources */,
-				BC8A45A1283DC33400094BBB /* KSCloudSettingView.m in Sources */,
 				BC119271280FAF7D00A716F7 /* AccompanyCourseInfoCell.m in Sources */,
 				BC2DFF5728BE143A0056105A /* HomeTempLiveCell.m in Sources */,
 				BC8C2C592823F57100FBA5D5 /* AddressListModel.m in Sources */,
@@ -7410,7 +7129,6 @@
 				275FA22D27E7356B00CFEA2E /* ChatViewController.m in Sources */,
 				BCC0F6E22A8CE24400C4EFA4 /* KSWhiteboardRefreshView.m in Sources */,
 				BC802DB828BC8C780079E350 /* HomeHotVideoCourseView.m in Sources */,
-				BC8A45A2283DC33400094BBB /* SettingPageView.m in Sources */,
 				2723B62627F157D500E0B90B /* GroupApplyViewController.m in Sources */,
 				BC31BF302B21925700F7D538 /* IACircularSlider.m in Sources */,
 				BC119293280FBC1100A716F7 /* HomeworkAddView.m in Sources */,

+ 39 - 16
KulexiuForStudent/KulexiuForStudent/Common/Base/AccompanyWebView/AudioEnginePlayer.m

@@ -22,10 +22,14 @@
 
 @property (nonatomic, strong) AVAudioFormat *audioFormat;
 
+@property (nonatomic, strong) dispatch_queue_t sourceQueue;
+
 @property (nonatomic, assign) NSTimeInterval totalDuration;
 
 @property (nonatomic, assign) AVAudioFramePosition startPosition; // 开始位置
 
+@property (nonatomic, assign) BOOL isPlayEnd;  // 是否播放完成
+
 @property (nonatomic, assign) BOOL isInterrupt; // 是否被打断
 
 @end
@@ -148,24 +152,26 @@
 }
 
 - (void)prepareNativeSongWithUrl:(NSURL *)nativeMusicUrl {
-    [self loadAudioFile:nativeMusicUrl];
-    
-    if (self.audioFile && self.audioFormat) {
-        [self configEngine];
-        // connect node
-        [self.audioEngine connect:self.bgPlayer to:self.timePitchUnit format:self.audioFormat];
-        [self.audioEngine connect:self.timePitchUnit to:self.audioEngine.mainMixerNode format:self.audioFormat];
-        
-        [self.audioEngine prepare];
-        
-        [self startEngine];
-        if (self.audioEngine && self.audioEngine.isRunning) {
-            if (self.delegate && [self.delegate respondsToSelector:@selector(enginePlayerIsReadyPlay:)]) {
-                [self.delegate enginePlayerIsReadyPlay:self];
+    dispatch_async(self.sourceQueue, ^{
+        [self loadAudioFile:nativeMusicUrl];
+        if (self.audioFile && self.audioFormat) {
+            [self configEngine];
+            // connect node
+            [self.audioEngine connect:self.bgPlayer to:self.timePitchUnit format:self.audioFormat];
+            [self.audioEngine connect:self.timePitchUnit to:self.audioEngine.mainMixerNode format:self.audioFormat];
+            
+            [self.audioEngine prepare];
+            
+            [self startEngine];
+            if (self.audioEngine && self.audioEngine.isRunning) {
+                dispatch_main_async_safe(^{
+                    if (self.delegate && [self.delegate respondsToSelector:@selector(enginePlayerIsReadyPlay:)]) {
+                        [self.delegate enginePlayerIsReadyPlay:self];
+                    }
+                });
             }
         }
-    }
-        
+    });
 }
 
 - (void)startEngine {
@@ -259,6 +265,8 @@
 
 
 - (void)startTimer {
+    NSLog(@"----- start timer ");
+    self.isPlayEnd = NO;
     [self.timer setFireDate:[NSDate distantPast]];
 }
 
@@ -290,6 +298,15 @@
     if (self.delegate && [self.delegate respondsToSelector:@selector(updatePlayProgress:andTotalTime:andProgress:currentInterval:inPlayer:)]) {
         [self.delegate updatePlayProgress:currentTime andTotalTime:self.totalDuration andProgress:progress currentInterval:inteveral*1000 inPlayer:self];
     }
+//    NSLog(@"------- current progress %f", progress);
+    if (progress >= 1 && self.isPlayEnd == NO) {
+        self.isPlayEnd = YES;
+        NSLog(@"0---isPlayEnd--------");
+        // 播放完成
+        if (self.delegate && [self.delegate respondsToSelector:@selector(enginePlayFinished:)]) {
+            [self.delegate enginePlayFinished:self];
+        }
+    }
 }
 
 - (void)setRate:(float)rate {
@@ -350,4 +367,10 @@
     return NO;
 }
 
+- (dispatch_queue_t)sourceQueue {
+    if (!_sourceQueue) {
+        _sourceQueue = dispatch_queue_create("KSAudioEnginePlayer_queue", DISPATCH_QUEUE_SERIAL);
+    }
+    return _sourceQueue;
+}
 @end

+ 92 - 49
KulexiuForStudent/KulexiuForStudent/Common/Base/AccompanyWebView/KSAccompanyWebViewController.m

@@ -458,7 +458,6 @@
     if (isBack) { // 页面销毁才删除
         if (_AQManager) {
             [_AQManager freeAudioQueue];
-            _AQManager = nil;
         }
         // 如果退出评测页面 清除 playerEngine
         if (self.playerEngine) {
@@ -507,27 +506,26 @@
             else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"startEvaluating"]) { // 开始评测
                 [self configRecordManager];
                 self.hasSendStartMessage = NO;
-                PREMISSIONTYPE isOk = [RecordCheckManager checkMicPermissionAvaiable];
-                if (isOk == PREMISSIONTYPE_YES) {
-                    self.evaluatParm = [NSMutableDictionary dictionaryWithDictionary:parm];
-                    // 如果socket 连上了
-                    if (self.socketManager.socketReadyState == SR_OPEN) {
-                        NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
-                        NSString *sendData = [self configDataCommond:@"musicXml" body:content type:@"SOUND_COMPARE"];
-                        [self sendDataToSocketService:sendData];
-                        [self postMessage:parm];
-                        self.hasSendStartMessage = YES;
+                [RecordCheckManager checkMicPermissionAvaiableCallback:^(PREMISSIONTYPE type) {
+                    if (type == PREMISSIONTYPE_YES) {
+                        self.evaluatParm = [NSMutableDictionary dictionaryWithDictionary:parm];
+                        // 如果socket 连上了
+                        if (self.socketManager.socketReadyState == SR_OPEN) {
+                            NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
+                            NSString *sendData = [self configDataCommond:@"musicXml" body:content type:@"SOUND_COMPARE"];
+                            [self sendDataToSocketService:sendData];
+                            [self postMessage:parm];
+                            self.hasSendStartMessage = YES;
+                        }
+                        else {
+                            [self connectSocketService];
+                        }
                     }
                     else {
-                        [self connectSocketService];
+                        [self responseMessage:@"storageUnable" desc:@"没有麦克风访问权限" parm:parm];
+                        [self showAlertWithMessage:@"请开启麦克风访问权限" type:CHECKDEVICETYPE_MIC];
                     }
-                }
-                else {
-                    NSDictionary *postParm = @{@"api" : @"cancelEvaluating",
-                                               @"content" : @{@"reson":@"没有麦克风权限"}
-                    };
-                    [self postMessage:postParm];
-                }
+                }];
             }
             else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"endEvaluating"]) {// 停止评测
                 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
@@ -597,18 +595,9 @@
                 [self sendDataToSocketService:sendData];
             }
             else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"openCamera"]) { // 开启摄像头
-                PREMISSIONTYPE canOpenCamera = [RecordCheckManager checkCameraPremissionAvaiable];
-                PREMISSIONTYPE albumEnable = [RecordCheckManager checkPhotoLibraryPremissionAvaiable];
-
-                if (canOpenCamera == PREMISSIONTYPE_YES) {
-                    self.isCameraOpen = YES;
-                    [self.videoRecordManager setIgnoreAudio:YES];
-                    [self.videoRecordManager configSessiondisplayInView:self.viewContainer];
-                    [self postMessage:parm];
-                }
-                if (albumEnable == PREMISSIONTYPE_NO) {
-                    [self showAlertWithMessage:@"请开启相册访问权限" type:CHECKDEVICETYPE_CAMREA];
-                }
+                [RecordCheckManager checkCameraPremissionAvaiableCallback:^(PREMISSIONTYPE type) {
+                    [self afterCheckCameraCheckAlbum:type parm:parm];
+                }];
                 
             }
             else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"closeCamera"]) { // 关闭摄像头
@@ -619,14 +608,18 @@
                 [self postMessage:parm];
             }
             else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"startCapture"]) { // 开始录制
-                PREMISSIONTYPE isOk = [RecordCheckManager checkPhotoLibraryPremissionAvaiable];
-                if (isOk == PREMISSIONTYPE_YES) {
-                    
-                    [self.videoRecordManager setIgnoreAudio:YES];
-                    self.videoRecordManager.audioUrl = self.AQManager.audioUrl;
-                    [self.videoRecordManager startRecord];
-                    [self postMessage:parm];
-                }
+                [RecordCheckManager checkPhotoLibraryPremissionAvaiableCallback:^(PREMISSIONTYPE type) {
+                    if (type == PREMISSIONTYPE_YES) {
+                        [self.videoRecordManager setIgnoreAudio:YES];
+                        self.videoRecordManager.audioUrl = self.AQManager.audioUrl;
+                        [self.videoRecordManager startRecord];
+                        [self postMessage:parm];
+                    }
+                    else {
+//                        [self responseMessage:@"storageUnable" desc:@"没有相册存储权限" parm:parm];
+//                        [self showAlertWithMessage:@"开启相册存储" type:CHECKDEVICETYPE_CAMREA];
+                    }
+                }];
             }
             else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"endCapture"]) { // 结束录制
                 if (self->_videoRecordManager) {
@@ -919,16 +912,25 @@
                 }
             }
             // 跟音
-            else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudToggleFollow"]) {
-                NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
-                NSString *status = [content ks_stringValueForKey:@"state"];
-                if ([status isEqualToString:@"start"]) { // 开始
-                    [self configAudioSession];
-                    [self startTuner];
-                }
-                else if ([status isEqualToString:@"end"]) { // 结束
-                    [self stopTuner];
-                }
+            else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudToggleFollow"]) { // 跟音
+                [RecordCheckManager checkMicPermissionAvaiableCallback:^(PREMISSIONTYPE type) {
+                    if (type == PREMISSIONTYPE_YES) {
+                        NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
+                        NSString *status = [content ks_stringValueForKey:@"state"];
+                        if ([status isEqualToString:@"start"]) { // 开始
+                            [self configAudioSession];
+                            [self startTuner];
+                        }
+                        else if ([status isEqualToString:@"end"]) { // 结束
+                            [self stopTuner];
+                        }
+                        [self postMessage:parm];
+                    }
+                    else {
+                        [self responseMessage:@"storageUnable" desc:@"没有麦克风权限" parm:parm];
+                        [self showAlertWithMessage:@"请开启麦克风访问权限" type:CHECKDEVICETYPE_MIC];
+                    }
+                }];
             }
             else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudAccompanyMessage"]) { // 获取伴奏 废弃⚠️
                 
@@ -1003,6 +1005,47 @@
     }
 }
 
+- (void)afterCheckCameraCheckAlbum:(PREMISSIONTYPE)cameraType parm:(NSDictionary *)sourceParm {
+    
+    [RecordCheckManager checkPhotoLibraryPremissionAvaiableCallback:^(PREMISSIONTYPE type) {
+        if (type == PREMISSIONTYPE_YES && cameraType == PREMISSIONTYPE_YES) {
+            self.isCameraOpen = YES;
+            [self.videoRecordManager setIgnoreAudio:YES];
+            [self.videoRecordManager configSessiondisplayInView:self.viewContainer];
+            [self postMessage:sourceParm];
+        }
+        else { //
+            
+            NSString *content = @"";
+            NSString *des = @"";;
+            if (cameraType == PREMISSIONTYPE_NO && type == PREMISSIONTYPE_NO) {
+                des = @"没有相机和相册访问权限";
+                content = @"请开启相机和相册访问权限";
+            }
+            else if (cameraType == PREMISSIONTYPE_NO && type == PREMISSIONTYPE_YES) {
+                des = @"没有相机访问权限";
+                content = @"请开启相机访问权限";
+            }
+            else if (cameraType == PREMISSIONTYPE_YES && type == PREMISSIONTYPE_NO) {
+                des = @"没有相册访问权限";
+                content = @"请开启相册访问权限";
+            }
+            [self responseMessage:@"storageUnable" desc:des parm:sourceParm];
+            [self showAlertWithMessage:content type:CHECKDEVICETYPE_CAMREA];
+
+        }
+    }];
+}
+
+- (void)responseMessage:(NSString *)reson desc:(NSString *)desc parm:(NSDictionary *)parm {
+    NSMutableDictionary *sendContent = [NSMutableDictionary dictionaryWithDictionary:[parm ks_dictionaryValueForKey:@"content"]];
+    [sendContent setValue:reson forKey:@"reson"];
+    [sendContent setValue:desc forKey:@"des"];
+    NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:parm];
+    [sendParm setValue:sendContent forKey:@"content"];
+    [self postMessage:sendParm];
+}
+
 - (void)musicPublishCallBack:(NSDictionary *)content {
     NSMutableDictionary *parm = [NSMutableDictionary dictionary];
     [parm setValue:@"hideComplexButton" forKey:@"api"];

+ 40 - 21
KulexiuForStudent/KulexiuForStudent/Common/Base/AccompanyWebView/KSCloudWebManager.m

@@ -53,29 +53,48 @@
 }
 
 - (void)showWebView:(NSDictionary *)parm fromController:(CustomNavViewController *)navCtrl {
-    PREMISSIONTYPE micEnable = [RecordCheckManager checkMicPermissionAvaiable];
-    PREMISSIONTYPE cameraEnable = [RecordCheckManager checkCameraPremissionAvaiable];
-    if (micEnable == PREMISSIONTYPE_YES && cameraEnable == PREMISSIONTYPE_YES) { //
-        KSCloudWebViewController *ctrl = [[KSCloudWebViewController alloc] init];
-        ctrl.webViewDelegate = self;
-        ctrl.url = [parm ks_stringValueForKey:@"url"];
-        ctrl.parmDic = parm;
-        NSInteger orientation = [parm ks_integerValueForKey:@"orientation"];
-        BOOL isLandScape = orientation == 0 ? YES : NO;
-        ctrl.ks_landScape = isLandScape;
-        [navCtrl pushViewController:ctrl animated:YES];
-    }
-    else {
-        if (micEnable == PREMISSIONTYPE_NO && cameraEnable == PREMISSIONTYPE_NO) { // 如果麦克风权限和摄像头权限都没有
-            [self showAlertWithMessage:@"请开启相机和麦克风访问权限" type:CHECKDEVICETYPE_BOTH];
-        }
-        else if (micEnable == PREMISSIONTYPE_NO) { // 如果没有麦克风权限
-            [self showAlertWithMessage:@"请开启麦克风访问权限" type:CHECKDEVICETYPE_MIC];
+    // 先检测相机 再检测麦克风
+    [RecordCheckManager checkCameraPremissionAvaiableCallback:^(PREMISSIONTYPE type) {
+        
+        [self afterCheckCameraCheckMic:type parm:parm fromController:navCtrl];
+    }];
+}
+
+- (void)afterCheckCameraCheckMic:(PREMISSIONTYPE)cameraType parm:(NSDictionary *)sourceParm fromController:(CustomNavViewController *)navCtrl {
+    
+    [RecordCheckManager checkMicPermissionAvaiableCallback:^(PREMISSIONTYPE type) {
+        if (type == PREMISSIONTYPE_YES && cameraType == PREMISSIONTYPE_YES) {
+            NSDictionary *valueDic = [sourceParm ks_dictionaryValueForKey:@"content"];
+            
+            KSCloudWebViewController *ctrl = [[KSCloudWebViewController alloc] init];
+            ctrl.webViewDelegate = self;
+            ctrl.url = [valueDic ks_stringValueForKey:@"url"];
+            ctrl.parmDic = valueDic;
+            NSInteger orientation = [valueDic ks_integerValueForKey:@"orientation"];
+            BOOL isLandScape = orientation == 0 ? YES : NO;
+            ctrl.ks_landScape = isLandScape;
+            [navCtrl pushViewController:ctrl animated:YES];
         }
-        else if (cameraEnable == PREMISSIONTYPE_NO) { // 如果没有摄像头权限
-            [self showAlertWithMessage:@"请开启相机访问权限" type:CHECKDEVICETYPE_CAMREA];
+        else { //
+            
+            NSString *content = @"";
+            CHECKDEVICETYPE checkType = CHECKDEVICETYPE_BOTH;
+            if (cameraType == PREMISSIONTYPE_NO && type == PREMISSIONTYPE_NO) {
+                content = @"请开启相机和麦克风访问权限";
+                checkType = CHECKDEVICETYPE_BOTH;
+            }
+            else if (cameraType == PREMISSIONTYPE_NO && type == PREMISSIONTYPE_YES) {
+                content = @"请开启相机访问权限";
+                checkType = CHECKDEVICETYPE_CAMREA;
+            }
+            else if (cameraType == PREMISSIONTYPE_YES && type == PREMISSIONTYPE_NO) {
+                content = @"请开启麦克风访问权限";
+                checkType = CHECKDEVICETYPE_MIC;
+            }
+            [self showAlertWithMessage:content type:checkType];
+
         }
-    }
+    }];
 }
 
 - (void)showAlertWithMessage:(NSString *)message type:(CHECKDEVICETYPE)deviceType {

+ 62 - 46
KulexiuForStudent/KulexiuForStudent/Common/Base/WebView/KSBaseWKWebViewController.m

@@ -395,37 +395,19 @@ typedef NS_ENUM(NSInteger, CHOOSETYPE) {
     }
     
     else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"openAccompanyWebView"]) { // 打开伴奏
-        PREMISSIONTYPE micEnable = [RecordCheckManager checkMicPermissionAvaiable];
-        PREMISSIONTYPE cameraEnable = [RecordCheckManager checkCameraPremissionAvaiable];
-        if (micEnable == PREMISSIONTYPE_YES && cameraEnable == PREMISSIONTYPE_YES) { // 如果麦克风和摄像头权限都有
-            NSDictionary *valueDic = [parm ks_dictionaryValueForKey:@"content"];
-            KSAccompanyWebViewController *detailCtrl = [[KSAccompanyWebViewController alloc] init];
-            detailCtrl.url = [valueDic ks_stringValueForKey:@"url"];
-            detailCtrl.parmDic = valueDic;
-            NSInteger orientation = [valueDic ks_integerValueForKey:@"orientation"];
-            BOOL isLandScape = orientation == 0 ? YES : NO;
-            detailCtrl.ks_landScape = isLandScape;
-            [self postMessage:parm];
-            [self.navigationController pushViewController:detailCtrl animated:YES];
-        }
-        else {
-            if (micEnable == PREMISSIONTYPE_NO && cameraEnable == PREMISSIONTYPE_NO) { // 如果麦克风权限和摄像头权限都没有
-                [self showAlertWithMessage:@"请开启相机和麦克风访问权限" type:CHECKDEVICETYPE_BOTH];
-            }
-            else if (micEnable == PREMISSIONTYPE_NO) { // 如果没有麦克风权限
-                [self showAlertWithMessage:@"请开启麦克风访问权限" type:CHECKDEVICETYPE_MIC];
-            }
-            else if (cameraEnable == PREMISSIONTYPE_NO) { // 如果没有摄像头权限
-                [self showAlertWithMessage:@"请开启相机访问权限" type:CHECKDEVICETYPE_CAMREA];
-            }
-        }
+        [RecordCheckManager checkCameraPremissionAvaiableCallback:^(PREMISSIONTYPE type) {
+            [self afterCheckCameraCheckMic:type parm:parm];
+        }];
     }
     else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"checkAlbum"]) { // 判断权限
-        [self postMessage:parm];
-        PREMISSIONTYPE albumEnable = [RecordCheckManager checkPhotoLibraryPremissionAvaiable];
-        if (albumEnable == PREMISSIONTYPE_NO) {
-            [self showAlertWithMessage:@"请开启相册访问权限" type:CHECKDEVICETYPE_CAMREA];
-        }
+        [RecordCheckManager checkPhotoLibraryPremissionAvaiableCallback:^(PREMISSIONTYPE type) {
+            if (type == PREMISSIONTYPE_YES) {
+                [self postMessage:parm];
+            }
+            else {
+                [self showAlertWithMessage:@"请开启相册访问权限" type:CHECKDEVICETYPE_CAMREA];
+            }
+        }];
     }
     else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"shareAchievements"]) { // 分享
         //
@@ -496,25 +478,24 @@ typedef NS_ENUM(NSInteger, CHOOSETYPE) {
     }
     else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"savePicture"]) { // 保存图片到相册
         // 判断相册权限
-        PREMISSIONTYPE albumEnable = [RecordCheckManager checkPhotoLibraryPremissionAvaiable];
-        if (albumEnable == PREMISSIONTYPE_YES) { // 如果有权限
-            NSDictionary *valueDic = [parm ks_dictionaryValueForKey:@"content"];
-            NSString *base64String = [valueDic ks_stringValueForKey:@"base64"];
-            UIImage *saveImage = [self imageWithBase64String:base64String];
-            [[TZImageManager manager] savePhotoWithImage:saveImage completion:^(PHAsset *asset, NSError *error) {
-                if (!error) {
-                    [self savePicCallback:[valueDic ks_stringValueForKey:@"uuid"] isSuccess:YES];
-                }
-                else {
-                    [self savePicCallback:[valueDic ks_stringValueForKey:@"uuid"] isSuccess:NO];
-                }
-            }];
-        }
-        else {
-            if (albumEnable == PREMISSIONTYPE_NO) {
+        [RecordCheckManager checkPhotoLibraryPremissionAvaiableCallback:^(PREMISSIONTYPE type) {
+            if (type == PREMISSIONTYPE_YES) {
+                NSDictionary *valueDic = [parm ks_dictionaryValueForKey:@"content"];
+                NSString *base64String = [valueDic ks_stringValueForKey:@"base64"];
+                UIImage *saveImage = [self imageWithBase64String:base64String];
+                [[TZImageManager manager] savePhotoWithImage:saveImage completion:^(PHAsset *asset, NSError *error) {
+                    if (!error) {
+                        [self savePicCallback:[valueDic ks_stringValueForKey:@"uuid"] isSuccess:YES];
+                    }
+                    else {
+                        [self savePicCallback:[valueDic ks_stringValueForKey:@"uuid"] isSuccess:NO];
+                    }
+                }];
+            }
+            else {
                 [self showAlertWithMessage:@"请开启相册访问权限" type:CHECKDEVICETYPE_CAMREA];
             }
-        }
+        }];
     }
     else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"getVersion"]) {
         NSDictionary *valueDic = [parm ks_dictionaryValueForKey:@"content"];
@@ -728,6 +709,41 @@ typedef NS_ENUM(NSInteger, CHOOSETYPE) {
     
 }
 
+- (void)afterCheckCameraCheckMic:(PREMISSIONTYPE)cameraType parm:(NSDictionary *)sourceParm {
+    
+    [RecordCheckManager checkMicPermissionAvaiableCallback:^(PREMISSIONTYPE type) {
+        if (type == PREMISSIONTYPE_YES && cameraType == PREMISSIONTYPE_YES) {
+            NSDictionary *valueDic = [sourceParm ks_dictionaryValueForKey:@"content"];
+            KSAccompanyWebViewController *detailCtrl = [[KSAccompanyWebViewController alloc] init];
+            detailCtrl.url = [valueDic ks_stringValueForKey:@"url"];
+            detailCtrl.parmDic = valueDic;
+            NSInteger orientation = [valueDic ks_integerValueForKey:@"orientation"];
+            BOOL isLandScape = orientation == 0 ? YES : NO;
+            detailCtrl.ks_landScape = isLandScape;
+            [self postMessage:sourceParm];
+            [self.navigationController pushViewController:detailCtrl animated:YES];
+        }
+        else { //
+            
+            NSString *content = @"";
+            CHECKDEVICETYPE checkType = CHECKDEVICETYPE_BOTH;
+            if (cameraType == PREMISSIONTYPE_NO && type == PREMISSIONTYPE_NO) {
+                content = @"请开启相机和麦克风访问权限";
+                checkType = CHECKDEVICETYPE_BOTH;
+            }
+            else if (cameraType == PREMISSIONTYPE_NO && type == PREMISSIONTYPE_YES) {
+                content =  @"请开启相机访问权限";
+                checkType = CHECKDEVICETYPE_CAMREA;
+            }
+            else if (cameraType == PREMISSIONTYPE_YES && type == PREMISSIONTYPE_NO) {
+                content = @"请开启麦克风访问权限";
+                checkType = CHECKDEVICETYPE_MIC;
+            }
+            [self showAlertWithMessage:content type:checkType];
+        }
+    }];
+}
+
 - (void)downloadWithParm:(NSDictionary *)parm {
     MJWeakSelf;
     [COURSEWARE_MANAGER downloadCourseWithParm:parm callback:^(NSDictionary * _Nonnull sendParm) {

+ 71 - 51
KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/KSMergeAudioControlView.m

@@ -9,7 +9,7 @@
 #import "UIView+KSCovertImage.h"
 #define MAX_OFFSET (600)
 
-@interface KSMergeAudioControlView ()<UIGestureRecognizerDelegate>
+@interface KSMergeAudioControlView ()
 
 @property (weak, nonatomic) IBOutlet UIView *bgView;
 
@@ -123,15 +123,6 @@
 }
 
 #pragma mark ----- 音量控制
-- (IBAction)changeRecordVolume:(UISlider *)sender {
-//    [self configRecordVolumeValue:sender.value];
-    
-}
-
-- (IBAction)changeBgVolume:(UISlider *)sender {
-//    [self configBgVolumeValue:sender.value];
-    
-}
 
 - (void)configRecordVolumeValue:(NSInteger)volume {
     self.recordVolume = volume;
@@ -146,9 +137,6 @@
             self.recordBubble.hidden = NO;
         }
     }];
-    if (self.callback) {
-        self.callback(MERGEACTION_MODIFY, self.recordVolume, self.bgVolume, self.offsetTime);
-    }
 }
 
 - (void)configBgVolumeValue:(NSInteger)volume {
@@ -162,9 +150,6 @@
             self.bgBubble.hidden =NO;
         }
     }];
-    if (self.callback) {
-        self.callback(MERGEACTION_MODIFY, self.recordVolume, self.bgVolume, self.offsetTime);
-    }
 }
 
 - (IBAction)cancleMerge:(id)sender {
@@ -196,9 +181,6 @@
 }
 
 - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
-    if (![[(UITouch *)touches.anyObject view] isEqual:self.sliderView] && ![[(UITouch *)touches.anyObject view] isEqual:self.recordGestureView] && ![[(UITouch *)touches.anyObject view] isEqual:self.bgGestureView] && ![[(UITouch *)touches.anyObject view] isEqual:self]) {
-        return;
-    }
     [super touchesMoved:touches withEvent:event];
     if ([[(UITouch *)touches.anyObject view] isEqual:self.sliderView]) {
         CGPoint tempPoint = [touches.anyObject locationInView:self.sliderView];
@@ -228,7 +210,6 @@
             xPosition = width;
         }
         NSInteger value =  (xPosition / width) * 100;
-         NSLog(@"---- record volume ---- %zd", value);
         [self.recordSlider setValue:value animated:YES];
         [self configRecordVolumeValue:value];
     }
@@ -243,34 +224,90 @@
             xPosition = width;
         }
         NSInteger value =  (xPosition / width) * 100;
-         NSLog(@"---- bg volume ---- %zd", value);
         [self.bgSlider setValue:value animated:YES];
         [self configBgVolumeValue:value];
     }
 }
 
 - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+    [super touchesEnded:touches withEvent:event];
     if ([[(UITouch *)touches.anyObject view] isEqual:self.recordGestureView]) {
-        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(500 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
-            self.recordBubble.hidden = YES;
-        });
-        return;
+        CGPoint tempPoint = [touches.anyObject locationInView:self.recordGestureView];
+        CGFloat xPosition = tempPoint.x;
+        CGFloat width = self.recordGestureView.frame.size.width;
+        if (xPosition < 0) {
+            xPosition = 0;
+        }
+        else if (xPosition > width) {
+            xPosition = width;
+        }
+        NSInteger value =  (xPosition / width) * 100;
+        [self refreshRecordValue:value];
     }
     else if ([[(UITouch *)touches.anyObject view] isEqual:self.bgGestureView]) {
-        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(500 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
-            self.bgBubble.hidden = YES;
-        });
-        return;
+        
+        CGPoint tempPoint = [touches.anyObject locationInView:self.bgGestureView];
+        CGFloat xPosition = tempPoint.x;
+        CGFloat width = self.recordGestureView.frame.size.width;
+        if (xPosition < 0) {
+            xPosition = 0;
+        }
+        else if (xPosition > width) {
+            xPosition = width;
+        }
+        NSInteger value =  (xPosition / width) * 100;
+        [self refreshBgValue:value];
+        
     }
-    if (![[(UITouch *)touches.anyObject view] isEqual:self.sliderView] && ![[(UITouch *)touches.anyObject view] isEqual:self]) {
-        return;
+    else if ([[(UITouch *)touches.anyObject view] isEqual:self.sliderView]) {
+        CGPoint tempPoint = [touches.anyObject locationInView:self.sliderView];
+        if (tempPoint.x <= 90.5) {
+            NSInteger offset = (NSInteger)(tempPoint.x - 90.5) / 3 * 10 * 2;
+            if (offset < -MAX_OFFSET) {
+                offset = -MAX_OFFSET;
+            }
+            self.offsetTime = offset;
+        }
+        else if (tempPoint.x > 90.5) {
+            NSInteger offset = (NSInteger)(tempPoint.x - 90.5) / 3 * 10 * 2;
+            if (offset > MAX_OFFSET) {
+                offset = MAX_OFFSET;
+            }
+            self.offsetTime = offset;
+        }
+        NSLog(@"---- offset - %zd", self.offsetTime);
+        if (self.callback) {
+            self.callback(MERGEACTION_DELAY, self.recordVolume, self.bgVolume, self.offsetTime);
+        }
     }
-    [super touchesEnded:touches withEvent:event];
+}
 
+- (void)refreshRecordValue:(NSInteger)value {
+    NSLog(@"---- record volume ---- %zd", value);
+    [self.recordSlider setValue:value animated:NO];
+    [self configRecordVolumeValue:value];
     if (self.callback) {
-        self.callback(MERGEACTION_DELAY, self.recordVolume, self.bgVolume, self.offsetTime);
+        self.callback(MERGEACTION_MODIFY, self.recordVolume, self.bgVolume, self.offsetTime);
     }
-    
+    @weakObj(self);
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(500 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
+        @strongObj(self);
+        self.recordBubble.hidden = YES;
+    });
+}
+
+- (void)refreshBgValue:(NSInteger)value {
+    NSLog(@"---- bg volume ---- %zd", value);
+    [self.bgSlider setValue:value animated:NO];
+    [self configBgVolumeValue:value];
+    if (self.callback) {
+        self.callback(MERGEACTION_MODIFY, self.recordVolume, self.bgVolume, self.offsetTime);
+    }
+    @weakObj(self);
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(500 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
+        @strongObj(self);
+        self.bgBubble.hidden = YES;
+    });
 }
 
 - (IBAction)leftAction:(id)sender {
@@ -301,23 +338,6 @@
     }
 }
 
-//进度条的点击事件
-- (void)actionTapGesture:(UITapGestureRecognizer *)gesture {
-    if (gesture.view == self.recordGestureView) {
-        CGPoint touchLocation = [gesture locationInView:self.recordGestureView];
-        CGFloat value = (self.recordSlider.maximumValue - self.recordSlider.minimumValue) * (touchLocation.x/self.recordSlider.frame.size.width);
-        [self.recordSlider setValue:value animated:YES];
-        [self configRecordVolumeValue:value];
-    }
-    else {
-        CGPoint touchLocation = [gesture locationInView:self.bgGestureView];
-        CGFloat value = (self.bgSlider.maximumValue - self.bgSlider.minimumValue) * (touchLocation.x/self.bgSlider.frame.size.width);
-        [self.bgSlider setValue:value animated:YES];
-        [self configBgVolumeValue:value];
-    }
-    
-}
-
 #pragma mark ------ lazying
 - (void)setOffsetTime:(NSInteger)offsetTime {
     _offsetTime = offsetTime;

+ 0 - 6
KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/KSMergeAudioControlView.xib

@@ -44,9 +44,6 @@
                             <color key="minimumTrackTintColor" red="0.1764705882" green="0.78039215689999997" blue="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                             <color key="maximumTrackTintColor" red="0.90980392156862744" green="0.92549019607843142" blue="0.94509803921568625" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                             <color key="thumbTintColor" red="0.1764705882" green="0.78039215689999997" blue="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <connections>
-                                <action selector="changeRecordVolume:" destination="iN0-l3-epB" eventType="valueChanged" id="WcD-V3-Jqt"/>
-                            </connections>
                         </slider>
                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="伴奏音量" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="if2-R5-Tul">
                             <rect key="frame" x="26" y="145" width="58" height="17"/>
@@ -59,9 +56,6 @@
                             <color key="minimumTrackTintColor" red="0.1764705882" green="0.78039215689999997" blue="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                             <color key="maximumTrackTintColor" red="0.90980392156862744" green="0.92549019607843142" blue="0.94509803921568625" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                             <color key="thumbTintColor" red="0.1764705882" green="0.78039215689999997" blue="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <connections>
-                                <action selector="changeBgVolume:" destination="iN0-l3-epB" eventType="valueChanged" id="vwy-ge-2aE"/>
-                            </connections>
                         </slider>
                         <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="DAF-iV-Mgw">
                             <rect key="frame" x="26" y="173" width="247" height="40"/>

+ 8 - 0
KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/KSPlayerSliderView.m

@@ -77,6 +77,13 @@
     self.progressTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(actionTapGesture:)];
     self.progressTap.delegate = self;
     [self.progressSlider addGestureRecognizer:self.progressTap];
+    // 获取 UISlider 内部的 panGestureRecognizer 并设置优先级
+    for (UIGestureRecognizer *gestureRecognizer in self.progressSlider.gestureRecognizers) {
+        if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
+            [self.progressTap requireGestureRecognizerToFail:gestureRecognizer];
+            break;
+        }
+    }
 }
 
 
@@ -125,6 +132,7 @@
 
 //视频进度条的点击事件
 - (void)actionTapGesture:(UITapGestureRecognizer *)sender {
+    self.isDragingSlider = NO;
     CGPoint touchLocation = [sender locationInView:self.progressSlider];
     CGFloat value = (self.progressSlider.maximumValue - self.progressSlider.minimumValue) * (touchLocation.x/self.progressSlider.frame.size.width);
     [self.progressSlider setValue:value animated:YES];

+ 27 - 0
KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergeAudioAnimation/KSRealtimeAnalyzer.h

@@ -0,0 +1,27 @@
+//
+//  KSRealtimeAnalyzer.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/7/29.
+//
+
+#import <Foundation/Foundation.h>
+#import <AVFoundation/AVFoundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface KSRealtimeAnalyzer : NSObject
+
+@property (nonatomic, assign) BOOL isAnalise; // 是否正在分析中
+
+@property (nonatomic, assign) NSInteger frequencyBands; // 频带数量
+@property (nonatomic, assign) float startFrequency; // 起始频率
+@property (nonatomic, assign) float endFrequency; // 截止频率
+@property (nonatomic, assign) float spectrumSmooth; // 频谱平滑
+
+- (instancetype)initWithFFTSize:(NSInteger)fftSize;
+- (NSArray<NSArray<NSNumber *> *> *)analyseWithBuffer:(AVAudioPCMBuffer *)buffer;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 256 - 0
KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergeAudioAnimation/KSRealtimeAnalyzer.m

@@ -0,0 +1,256 @@
+//
+//  KSRealtimeAnalyzer.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/7/29.
+//
+
+#import "KSRealtimeAnalyzer.h"
+#import <Accelerate/Accelerate.h>
+
+@interface KSRealtimeAnalyzer ()
+
+@property (nonatomic, assign) NSInteger fftSize;
+@property (nonatomic, assign) FFTSetup fftSetup;
+@property (nonatomic, strong) NSArray<NSArray<NSNumber *> *> *bands;
+@property (nonatomic, strong) NSMutableArray<NSMutableArray<NSNumber *> *> *spectrumBuffer;
+
+@property (nonatomic, assign) float *realp;
+@property (nonatomic, assign) float *imagp;
+
+@property (nonatomic, strong) NSArray<NSNumber *> *cachedFrequencyWeights;
+
+@end
+
+@implementation KSRealtimeAnalyzer
+
+- (instancetype)initWithFFTSize:(NSInteger)fftSize {
+    self = [super init];
+    if (self) {
+        _fftSize = fftSize;
+        _fftSetup = vDSP_create_fftsetup(log2(_fftSize), FFT_RADIX2);
+        _realp = (float *)calloc(_fftSize / 2, sizeof(float));
+        _imagp = (float *)calloc(_fftSize / 2, sizeof(float));
+        _frequencyBands = 80;
+        _startFrequency = 100.0;
+        _endFrequency = 18000.0;
+        _spectrumSmooth = 0.5;
+        _spectrumBuffer = [NSMutableArray array];
+        [self setupBands];
+        _cachedFrequencyWeights = [self createFrequencyWeights];
+    }
+    return self;
+}
+
+- (void)dealloc {
+    vDSP_destroy_fftsetup(_fftSetup);
+    free(_realp);
+    free(_imagp);
+    NSLog(@"-------KSRealtimeAnalyzer dealloc");
+}
+
+- (void)setupBands {
+    NSMutableArray *bands = [NSMutableArray array];
+    float n = log2(self.endFrequency / self.startFrequency) / self.frequencyBands;
+    float lowerFrequency = self.startFrequency;
+
+    for (NSInteger i = 0; i < self.frequencyBands; i++) {
+        float upperFrequency = (i == self.frequencyBands - 1) ? self.endFrequency : lowerFrequency * powf(2, n);
+        [bands addObject:@{@"lowerFrequency": @(lowerFrequency), @"upperFrequency": @(upperFrequency)}];
+        lowerFrequency = upperFrequency;
+    }
+    
+    self.bands = [bands copy];
+}
+
+- (NSArray<NSArray<NSNumber *> *> *)analyseWithBuffer:(AVAudioPCMBuffer *)buffer {
+    self.isAnalise = YES;
+    NSArray<NSArray<NSNumber *> *> *channelsAmplitudes = [self fftWithBuffer:buffer];
+    NSArray<NSNumber *> *aWeights = self.cachedFrequencyWeights;
+    if (self.spectrumBuffer.count == 0) {
+        for (NSInteger i = 0; i < channelsAmplitudes.count; i++) {
+            [self.spectrumBuffer addObject:[self emptyArrayOfCount:self.bands.count]];
+        }
+    }
+    
+    NSMutableArray<NSArray<NSNumber *> *> *result = [NSMutableArray arrayWithArray:self.spectrumBuffer];
+    // 放大倍数
+    CGFloat amplificationFactor = 40.0; // 调整为所需的放大倍数
+    dispatch_apply(channelsAmplitudes.count, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {
+        NSArray<NSNumber *> *amplitudes = channelsAmplitudes[index];
+        NSMutableArray<NSNumber *> *weightedAmplitudes = [NSMutableArray arrayWithCapacity:amplitudes.count];
+        
+        for (NSInteger i = 0; i < amplitudes.count; i++) {
+            weightedAmplitudes[i] = @(amplitudes[i].floatValue * aWeights[i].floatValue);
+        }
+        
+        NSMutableArray<NSNumber *> *spectrum = [NSMutableArray arrayWithCapacity:self.bands.count];
+        
+        for (NSDictionary *band in self.bands) {
+            float bandWidth = (float)buffer.format.sampleRate / self.fftSize;
+            [spectrum addObject:@([self findMaxAmplitudeForBand:band inAmplitudes:weightedAmplitudes withBandWidth:bandWidth] * amplificationFactor)];
+        }
+        
+        spectrum = [self highlightWaveform:spectrum];
+        
+        NSMutableArray<NSNumber *> *previousSpectrum = [self.spectrumBuffer[index] mutableCopy];
+        NSMutableArray<NSNumber *> *newSpectrum = [NSMutableArray arrayWithCapacity:spectrum.count];
+        
+        for (NSInteger i = 0; i < spectrum.count; i++) {
+            float smoothedValue = ([previousSpectrum[i] floatValue] * self.spectrumSmooth) + (spectrum[i].floatValue * (1 - self.spectrumSmooth));
+            newSpectrum[i] = @(smoothedValue);
+        }
+        
+        result[index] = [newSpectrum copy];
+        self.spectrumBuffer[index] = [newSpectrum copy];
+    });
+    self.isAnalise = NO;
+    return [result copy];
+}
+
+
+- (NSArray<NSArray<NSNumber *> *> *)fftWithBuffer:(AVAudioPCMBuffer *)buffer {
+    NSMutableArray<NSMutableArray<NSNumber *> *> *amplitudes = [NSMutableArray array];
+    float *const _Nonnull *floatChannelData = buffer.floatChannelData;
+    NSInteger channelCount = buffer.format.channelCount;
+    BOOL isInterleaved = buffer.format.isInterleaved;
+
+    float **tempFloatChannelData = NULL;
+    
+    if (isInterleaved) {
+        NSMutableArray<NSMutableData *> *channelsTemp = [NSMutableArray array];
+        float *interleavedData = floatChannelData[0];
+        for (NSInteger i = 0; i < channelCount; i++) {
+            NSMutableData *channelData = [NSMutableData dataWithLength:self.fftSize * sizeof(float)];
+            float *channelDataPtr = (float *)channelData.mutableBytes;
+            for (NSInteger j = i; j < self.fftSize * channelCount; j += channelCount) {
+                channelDataPtr[j / channelCount] = interleavedData[j];
+            }
+            [channelsTemp addObject:channelData];
+        }
+        
+        tempFloatChannelData = (float **)malloc(channelCount * sizeof(float *));
+        for (NSInteger i = 0; i < channelCount; i++) {
+            tempFloatChannelData[i] = (float *)[channelsTemp[i] mutableBytes];
+        }
+        
+        floatChannelData = (float *const _Nonnull *)tempFloatChannelData;
+    }
+    
+    for (NSInteger i = 0; i < channelCount; i++) {
+        float *channel = floatChannelData[i];
+        NSMutableData *windowData = [NSMutableData dataWithLength:self.fftSize * sizeof(float)];
+        float *window = windowData.mutableBytes;
+        vDSP_hann_window(window, self.fftSize, vDSP_HANN_NORM);
+        vDSP_vmul(channel, 1, window, 1, channel, 1, self.fftSize);
+        
+        DSPSplitComplex fftInOut;
+        fftInOut.realp = self.realp;
+        fftInOut.imagp = self.imagp;
+        
+        vDSP_ctoz((DSPComplex *)channel, 2, &fftInOut, 1, self.fftSize / 2);
+        vDSP_fft_zrip(self.fftSetup, &fftInOut, 1, log2(self.fftSize), FFT_FORWARD);
+        
+        fftInOut.imagp[0] = 0;
+        float fftNormFactor = 1.0 / self.fftSize;
+        vDSP_vsmul(fftInOut.realp, 1, &fftNormFactor, fftInOut.realp, 1, self.fftSize / 2);
+        vDSP_vsmul(fftInOut.imagp, 1, &fftNormFactor, fftInOut.imagp, 1, self.fftSize / 2);
+        
+        NSMutableArray<NSNumber *> *channelAmplitudes = [NSMutableArray arrayWithCapacity:self.fftSize / 2];
+        float *amplitudesArray = (float *)calloc(self.fftSize / 2, sizeof(float));
+        vDSP_zvabs(&fftInOut, 1, amplitudesArray, 1, self.fftSize / 2);
+        amplitudesArray[0] /= 2;
+        
+        for (NSInteger j = 0; j < self.fftSize / 2; j++) {
+            channelAmplitudes[j] = @(amplitudesArray[j]);
+        }
+        
+        [amplitudes addObject:[channelAmplitudes copy]];
+//        free(fftInOut.realp);
+//        free(fftInOut.imagp);
+        free(amplitudesArray);
+    }
+    
+    if (isInterleaved) {
+        free(tempFloatChannelData);
+    }
+    
+    return [amplitudes copy];
+}
+
+- (float)findMaxAmplitudeForBand:(NSDictionary *)band inAmplitudes:(NSArray<NSNumber *> *)amplitudes withBandWidth:(float)bandWidth {
+    NSInteger startIndex = round([band[@"lowerFrequency"] floatValue] / bandWidth);
+    NSInteger endIndex = MIN(round([band[@"upperFrequency"] floatValue] / bandWidth), amplitudes.count - 1);
+    float maxAmplitude = -FLT_MAX;
+    for (NSInteger i = startIndex; i <= endIndex; i++) {
+        float amplitude = [amplitudes[i] floatValue];
+        if (amplitude > maxAmplitude) {
+            maxAmplitude = amplitude;
+        }
+    }
+    return maxAmplitude;
+}
+
+- (NSArray<NSNumber *> *)createFrequencyWeights {
+    float sampleRate = 44100.0;
+    NSInteger fftSize = self.fftSize;
+    float deltaFrequency = sampleRate / fftSize;
+    NSInteger bins = fftSize / 2;
+
+    // 预先计算常量
+    float c1 = powf(12194.217, 2.0);
+    float c2 = powf(20.598997, 2.0);
+    float c3 = powf(107.65265, 2.0);
+    float c4 = powf(737.86223, 2.0);
+
+    NSMutableArray<NSNumber *> *frequencies = [NSMutableArray arrayWithCapacity:bins];
+    NSMutableArray<NSNumber *> *weights = [NSMutableArray arrayWithCapacity:bins];
+
+    for (NSInteger i = 0; i < bins; i++) {
+        float frequency = i * deltaFrequency;
+        [frequencies addObject:@(frequency)];
+    }
+
+    for (NSInteger i = 0; i < bins; i++) {
+        float frequencySquared = [frequencies[i] floatValue] * [frequencies[i] floatValue];
+
+        float numerator = c1 * frequencySquared * frequencySquared;
+        float denominator = (frequencySquared + c2) * sqrtf((frequencySquared + c3) * (frequencySquared + c4)) * (frequencySquared + c1);
+
+        float weight = 1.2589 * numerator / denominator;
+        [weights addObject:@(weight)];
+    }
+
+    return [weights copy];
+}
+
+- (NSMutableArray<NSNumber *> *)highlightWaveform:(NSArray<NSNumber *> *)spectrum {
+    float weights[] = {1, 2, 3, 5, 3, 2, 1};
+    float totalWeights = 17.0; // 1 + 2 + 3 + 5 + 3 + 2 + 1
+    NSInteger weightsCount = sizeof(weights) / sizeof(weights[0]);
+    NSInteger startIndex = weightsCount / 2;
+    NSMutableArray<NSNumber *> *averagedSpectrum = [NSMutableArray arrayWithArray:[spectrum subarrayWithRange:NSMakeRange(0, startIndex)]];
+    // 直接复制开始部分
+    [averagedSpectrum addObjectsFromArray:[spectrum subarrayWithRange:NSMakeRange(0, startIndex)]];
+    // 使用 vDSP 函数来加权平滑
+    for (NSInteger i = startIndex; i < spectrum.count - startIndex; i++) {
+        float result = 0;
+        for (NSInteger j = 0; j < weightsCount; j++) {
+            result += [spectrum[i - startIndex + j] floatValue] * weights[j];
+        }
+        [averagedSpectrum addObject:@(result / totalWeights)];
+    }
+    // 复制结束部分
+    [averagedSpectrum addObjectsFromArray:[spectrum subarrayWithRange:NSMakeRange(spectrum.count - startIndex, startIndex)]];
+    return [averagedSpectrum mutableCopy];
+}
+
+- (NSMutableArray<NSNumber *> *)emptyArrayOfCount:(NSUInteger)count {
+    NSMutableArray<NSNumber *> *array = [NSMutableArray arrayWithCapacity:count];
+    for (NSUInteger i = 0; i < count; i++) {
+        [array addObject:@(0.0)];
+    }
+    return array;
+}
+
+@end

+ 23 - 0
KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergeAudioAnimation/KSSpectrumView.h

@@ -0,0 +1,23 @@
+//
+//  KSSpectrumView.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/7/29.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface KSSpectrumView : UIView
+
+@property (nonatomic, assign) CGFloat barWidth;
+@property (nonatomic, assign) CGFloat space;
+
+@property (nonatomic, strong) NSArray<NSArray<NSNumber *> *> *spectra;
+
+- (void)resetLayer;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 109 - 0
KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergeAudioAnimation/KSSpectrumView.m

@@ -0,0 +1,109 @@
+//
+//  KSSpectrumView.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/7/29.
+//
+
+#import "KSSpectrumView.h"
+
+@interface KSSpectrumView ()
+
+@property (nonatomic, strong) CAGradientLayer *combinedGradientLayer;
+
+@end
+
+@implementation KSSpectrumView
+
+- (instancetype)initWithFrame:(CGRect)frame {
+    self = [super initWithFrame:frame];
+    if (self) {
+        [self setupView];
+    }
+    return self;
+}
+
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+    self = [super initWithCoder:aDecoder];
+    if (self) {
+        [self setupView];
+    }
+    return self;
+}
+
+- (void)setupView {
+    self.barWidth = 3.0;
+    self.space = 1.0;
+
+    self.combinedGradientLayer = [CAGradientLayer layer];
+    self.combinedGradientLayer.colors = @[
+        (__bridge id)HexRGBAlpha(0xffffff, 0.32f).CGColor,
+        (__bridge id)HexRGBAlpha(0xffffff, 0.32f).CGColor
+    ];
+    self.combinedGradientLayer.locations = @[@0.6, @1.0];
+    [self.layer addSublayer:self.combinedGradientLayer];
+}
+
+- (void)resetLayer {
+    self.spectra = [NSArray array];
+}
+
+- (void)setSpectra:(NSArray<NSArray<NSNumber *> *> *)spectra {
+    _spectra = spectra;
+    if (spectra) {
+        NSUInteger spectraCount = [spectra[0] count];
+        NSMutableArray<NSNumber *> *combinedSpectrum = [NSMutableArray arrayWithCapacity:spectraCount];
+        // 取两个声道数据中的最大值
+        for (NSUInteger i = 0; i < spectraCount; i++) {
+            NSNumber *leftAmplitude = spectra[0][i];
+            NSNumber *rightAmplitude = spectra.count > 1 ? spectra[1][i] : @0;
+            CGFloat maxAmplitude = MAX(leftAmplitude.floatValue, rightAmplitude.floatValue);
+            [combinedSpectrum addObject:@(maxAmplitude)];
+        }
+        
+        CGFloat viewHeight = self.bounds.size.height;
+        CGFloat viewWidth = self.bounds.size.width;
+        CGFloat middleY = viewHeight / 2.0;
+        CGFloat barHeight = (viewHeight) / 2.0;
+        CGFloat cornerRadius = viewWidth / 2.0f;
+        CGFloat xIncrement = self.barWidth + self.space;
+        UIBezierPath *combinedPath = [UIBezierPath bezierPath];
+
+        // Left channel
+        for (NSUInteger i = 0; i < spectraCount; i++) {
+            CGFloat x = i * xIncrement + self.space;
+            CGFloat amplitudeValue = combinedSpectrum[i].floatValue;
+            CGFloat height = amplitudeValue * barHeight;
+            CGFloat y = middleY - height/2.0; // Centered vertically
+            
+            CGRect rect = CGRectMake(x, y, self.barWidth, height);
+            UIBezierPath *barPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
+            [combinedPath appendPath:barPath];
+        }
+        
+        CAShapeLayer *combinedMaskLayer = [CAShapeLayer layer];
+        combinedMaskLayer.path = combinedPath.CGPath;
+        self.combinedGradientLayer.frame = CGRectMake(0, 0, viewWidth, viewHeight);
+        self.combinedGradientLayer.mask = combinedMaskLayer;
+
+    }
+}
+
+- (CGFloat)translateAmplitudeToYPosition:(float)amplitude {
+    CGFloat barHeight = amplitude * self.bounds.size.height;
+    return self.bounds.size.height - barHeight;
+}
+
+- (void)dealloc {
+    NSLog(@"---- KSSpectrumView dealloc");
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 7 - 1
KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergePlayer/KSMergeEnginePlayer.h

@@ -6,6 +6,7 @@
 //
 
 #import <Foundation/Foundation.h>
+#import "KSRealtimeAnalyzer.h"
 
 @class KSMergeEnginePlayer;
 
@@ -26,7 +27,10 @@
 
 - (void)enginePlayerIsReadyPlay:(KSMergeEnginePlayer *_Nonnull)player;
 
-- (void)enginePlayerDidError:(KSMergeEnginePlayer *_Nonnull)player error:(NSError *_Nullable)error;
+- (void)enginePlayerDidError:(KSMergeEnginePlayer *_Nonnull)player error:(NSError *_Nonnull)error;
+
+// 动效相关
+- (void)player:(KSMergeEnginePlayer *_Nonnull)player didGenerateSpectrum:(NSArray<NSArray<NSNumber *> *> *_Nonnull)spectra;
 
 @end
 
@@ -34,6 +38,8 @@ NS_ASSUME_NONNULL_BEGIN
 
 @interface KSMergeEnginePlayer : NSObject
 
+@property (nonatomic, strong) KSRealtimeAnalyzer *analyzer;
+
 @property (nonatomic, weak) id <KSMergeEnginePlayerDelegate>delegate;
 
 @property (nonatomic, assign) BOOL isReady;

+ 218 - 201
KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergePlayer/KSMergeEnginePlayer.m

@@ -7,8 +7,11 @@
 
 #import "KSMergeEnginePlayer.h"
 #import <AVFoundation/AVFoundation.h>
+#import <Accelerate/Accelerate.h>
 
+#define READ_FILE_LENGTH (8192)
 
+#define BUFFER_SIZE (2048)
 
 @interface KSMergeEnginePlayer ()
 /** 定时器 */
@@ -34,24 +37,14 @@
 
 @property (nonatomic, strong) AVAudioPCMBuffer *mixBuffer;
 
-@property (nonatomic, strong) AVAudioPCMBuffer *bgBuffer;
-
-@property (nonatomic, strong) AVAudioPCMBuffer *recordBuffer;
-
 @property (nonatomic, assign) AVAudioFramePosition currentFrame;
 
 @property (nonatomic, assign) double sampleRate;
 
-@property (nonatomic, assign) BOOL stopMix; // 是否停止mix
-
-@property (nonatomic, strong) dispatch_semaphore_t mixChangeSemaphore; // mix信号量
-
-@property (nonatomic, assign) BOOL stopChangeVolume; // 是否停止音量修改循环
-
-@property (nonatomic, strong) dispatch_semaphore_t volumeChangeSemaphore;
-
 @property (nonatomic, assign) BOOL isInterrupt; // 是否被打断
 
+@property (nonatomic, assign) NSInteger timeCount;
+
 @end
 
 
@@ -68,8 +61,6 @@
 - (void)configDefault {
     self.recordVolume = 1.0f;
     self.bgVolume = 1.0f;
-    self.mixChangeSemaphore = dispatch_semaphore_create(1); // 初始化信号量
-    self.volumeChangeSemaphore = dispatch_semaphore_create(1); // 初始化信号量,初始值为1
 }
 
 - (void)configEngine {
@@ -111,225 +102,235 @@
         if (error) {
             self.audioEngine = nil;
             // 错误回调
-            [self sendInterruptError:error];
+            if (self.delegate && [self.delegate respondsToSelector:@selector(enginePlayerDidError:error:)]) {
+                [self.delegate enginePlayerDidError:self error:error];
+            }
         }
     }
 }
 
 - (void)prepareNativeSongWithUrl:(NSURL *)recordAudioUrl bgMusic:(NSURL *)bgMusicUrl {
-    [self loadAuidoFile:recordAudioUrl isBgm:NO];
-    [self loadAuidoFile:bgMusicUrl isBgm:YES];
-    self.sampleRate = self.audioFile.fileFormat.sampleRate;
-    [self configEngine];
-    
-    AVAudioFormat *outputFormat = [self.audioEngine.mainMixerNode outputFormatForBus:0];
-    [self.audioEngine connect:self.nodePlayer to:self.audioEngine.mainMixerNode format:outputFormat];
-    [self startEngine];
-    
-    if (self.audioEngine && self.audioEngine.isRunning) {
-        dispatch_async(self.sourceQueue, ^{
+    dispatch_async(self.sourceQueue, ^{
+        
+        [self loadAuidoFile:recordAudioUrl isBgm:NO];
+        [self loadAuidoFile:bgMusicUrl isBgm:YES];
+        self.sampleRate = self.audioFile.fileFormat.sampleRate;
+        [self configEngine];
+        
+        AVAudioFormat *outputFormat = [self.audioEngine.mainMixerNode outputFormatForBus:0];
+        [self.audioEngine connect:self.nodePlayer to:self.audioEngine.mainMixerNode format:outputFormat];
+//        [self addTapBus];
+        [self startEngine];
+        
+        if (self.audioEngine && self.audioEngine.isRunning) {
             [self prepareBufferFrame];
-        });
-    }
+        }
+    });
 }
 
+- (void)addTapBus {
+    BOOL delegateRespondsToDidGenerateSpectrum = [self.delegate respondsToSelector:@selector(player:didGenerateSpectrum:)];
+    self.analyzer = [[KSRealtimeAnalyzer alloc] initWithFFTSize:BUFFER_SIZE];
+    AVAudioFormat *outputFormat = [self.audioEngine.mainMixerNode outputFormatForBus:0];
+    @weakObj(self);
+    [self.audioEngine.mainMixerNode removeTapOnBus:0];
+    [self.audioEngine.mainMixerNode installTapOnBus:0 bufferSize:BUFFER_SIZE format:outputFormat block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) {
+        @strongObj(self);
+        if (!self || !self.nodePlayer.isPlaying) {
+            return;
+        }
+        // 将频谱分析任务提交到后台队列
+            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
+                if (self.analyzer.isAnalise == NO) {
+                    // 分析音频缓冲区
+                    NSArray<NSArray<NSNumber *> *> *spectra = [self.analyzer analyseWithBuffer:buffer];
+                    
+                    // 回到主线程更新 UI 或调用委托方法
+                    dispatch_async(dispatch_get_main_queue(), ^{
+                        if (delegateRespondsToDidGenerateSpectrum) {
+                            [self.delegate player:self didGenerateSpectrum:spectra];
+                        }
+                    });
+                }
+            });
+    }];
+}
 
 - (void)loadAuidoFile:(NSURL *)audioFileUrl isBgm:(BOOL)isBgm {
-    dispatch_sync(self.sourceQueue, ^{
-        NSError *error = nil;
-        AVAudioFile *audioFile = nil;
-        AVAudioFormat *audioFormat = nil;
-        @try {
-            audioFile = [[AVAudioFile alloc] initForReading:audioFileUrl error:&error];
-            audioFormat = audioFile.processingFormat;
-            
-        } @catch (NSException *exception) {
-            audioFile = nil;
-            audioFormat = nil;
-        } @finally {
-            if (error) {
-                // 错误回调
+    NSError *error = nil;
+    AVAudioFile *audioFile = nil;
+    AVAudioFormat *audioFormat = nil;
+    @try {
+        audioFile = [[AVAudioFile alloc] initForReading:audioFileUrl error:&error];
+        audioFormat = audioFile.processingFormat;
+        
+    } @catch (NSException *exception) {
+        audioFile = nil;
+        audioFormat = nil;
+    } @finally {
+        if (error) {
+            // 错误回调
+        }
+        else { // 加载成功
+            if (isBgm) {
+                self.bgAudioFile = audioFile;
+                self.bgAudioFormat = audioFormat;
             }
-            else { // 加载成功
-                if (isBgm) {
-                    self.bgAudioFile = audioFile;
-                    self.bgAudioFormat = audioFormat;
-                }
-                else {
-                    self.audioFile = audioFile;
-                    self.audioFormat = audioFormat;
-                }
+            else {
+                self.audioFile = audioFile;
+                self.audioFormat = audioFormat;
             }
         }
-    });
+    }
 }
 
-- (void)prepareBufferFrame {
+- (void)resetMixBuffer {
     AVAudioFrameCount minFrameCount = (AVAudioFrameCount)MIN(self.bgAudioFile.length, self.audioFile.length);
     // mixBuffer
     AVAudioFormat *outputFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:self.bgAudioFormat.sampleRate channels:2];
     self.mixBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:outputFormat frameCapacity:minFrameCount];
     self.mixBuffer.frameLength = minFrameCount;
-    
-    self.bgBuffer = [self loadAudioSegment:self.bgAudioFile startFrame:0 frameCount:minFrameCount];
-    self.recordBuffer = [self loadAudioSegment:self.audioFile startFrame:0 frameCount:minFrameCount];
-    
-    if (self.delegate && [self.delegate respondsToSelector:@selector(enginePlayerIsReadyPlay:)]) {
-        self.isReady = YES;
-        [self.delegate enginePlayerIsReadyPlay:self];
-    }
 }
 
-- (AVAudioPCMBuffer *)loadAudioSegment:(AVAudioFile *)audioFile startFrame:(AVAudioFramePosition)startFrame frameCount:(AVAudioFrameCount)frameCount {
-    AVAudioFormat *audioFromat = audioFile.processingFormat;
-    AVAudioFrameCount frameToRead = (AVAudioFrameCount)MIN(frameCount, (AVAudioFrameCount)audioFile.length - startFrame);
-    if (startFrame > audioFile.length) {
-        return nil;
-    }
-    AVAudioPCMBuffer *buffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:audioFromat frameCapacity:frameToRead];
-    buffer.frameLength = frameToRead;
-    
-    audioFile.framePosition = startFrame;
-    if (frameToRead > 0) {
-        @try {
-            [audioFile readIntoBuffer:buffer frameCount:frameToRead error:nil];
-        } @catch (NSException *exception) {
-            
-        } @finally {
-            
+- (void)prepareBufferFrame {
+    [self resetMixBuffer];
+    dispatch_main_async_safe(^{
+        if (self.delegate && [self.delegate respondsToSelector:@selector(enginePlayerIsReadyPlay:)]) {
+            self.isReady = YES;
+            [self.delegate enginePlayerIsReadyPlay:self];
         }
-    }
-    return buffer;
+    });
 }
 
-
-- (void)mixBuffers:(AVAudioPCMBuffer *)bgBuffer bgBufferVolume:(float)bgBufferVolume withRecordBuffer:(AVAudioPCMBuffer *)recordBuffer recordVolume:(float)recordVolume offset:(NSInteger)offsetTime startPosition:(AVAudioFrameCount)startPosition {
-    if (!bgBuffer && !recordBuffer) {
-        return;
-    }
-    NSLog(@"------- start");
-    
-    AVAudioFrameCount minFrameCount = MIN(bgBuffer.frameLength, recordBuffer.frameLength);
-    AVAudioFrameCount offsetFrame = labs(offsetTime)/1000.0 * recordBuffer.format.sampleRate;
+// 预计加载buffer
+- (void)prepareBuffer:(AVAudioFramePosition)startPosition offset:(NSInteger)offsetTime mixStart:(AVAudioFramePosition)mixStartPosition {
     
-    float *bgLeftChannel = bgBuffer.floatChannelData[0];
-    float *bgRightChannel = bgBuffer.floatChannelData[1];
-    // 录音文件未单声道
-    float *recordLeftChannel = recordBuffer.floatChannelData[0];
-    
-    float *mixLeftChannel = self.mixBuffer.floatChannelData[0];
-    float *mixRightChannel = self.mixBuffer.floatChannelData[1];
-    
-    for (int frame = 0; frame < minFrameCount; frame++) {
-        if (self.stopMix) {
-            NSLog(@"------- stop mix");
-            dispatch_semaphore_signal(self.mixChangeSemaphore); // 释放信号量
+    dispatch_async(self.sourceQueue, ^{
+        if (!self.bgAudioFile || !self.audioFile) {
             return;
         }
-        int bgFrame = frame+startPosition;
-        float leftChannel = (bgFrame < bgBuffer.frameLength) ? bgLeftChannel[bgFrame] : 0;
-        float rightChannel = (bgFrame < bgBuffer.frameLength) ? bgRightChannel[bgFrame] : 0;
-        
-        int recordFrame = (offsetTime < 0) ? (bgFrame - offsetFrame) : (bgFrame + offsetFrame);
-        
-        float recordData = (recordFrame >= 0 && recordFrame < recordBuffer.frameLength) ? recordLeftChannel[recordFrame] : 0;
-        
-        
-        float mixLeftData = [self mixChannelData:leftChannel bgVolume:bgBufferVolume recordData:recordData recordVolume:recordVolume];
-        float mixRightData = [self mixChannelData:rightChannel bgVolume:bgBufferVolume recordData:recordData recordVolume:recordVolume];
+        AVAudioFramePosition minFrameCount = (AVAudioFramePosition)MIN(self.bgAudioFile.length, self.audioFile.length);
+        AVAudioFrameCount offsetFrame = labs(offsetTime)/1000.0 * self.audioFile.processingFormat.sampleRate;
+        if (minFrameCount <= startPosition) {
+            return;
+        }
+        AVAudioFrameCount frameToRead = minFrameCount - startPosition > READ_FILE_LENGTH ? READ_FILE_LENGTH : (AVAudioFrameCount)(minFrameCount - startPosition);
         
-        mixLeftChannel[frame] = MAX(-1.0, MIN(1.0, mixLeftData));
-        mixRightChannel[frame] = MAX(-1.0, MIN(1.0, mixRightData));
-    }
-    NSLog(@"---------finish");
-    
-}
-
-- (float)mixChannelData:(float)bgData bgVolume:(float)bgVolume recordData:(float)recordData recordVolume:(float)recordVolume {
-    return (bgData * bgVolume + recordData * recordVolume) / 2;
-}
-
-- (void)changeVolume:(float)bgVolume recordVolume:(float)recordVolume {
-    
-    NSLog(@"bg volume ---- %f,  record volume ---- %f", bgVolume, recordVolume);
-    self.bgVolume = bgVolume;
-    self.recordVolume = recordVolume;
-    if (self.bgBuffer && self.recordBuffer) {
-        self.stopChangeVolume = YES;
-        // 停止上一次修改音量
-        dispatch_async(self.sourceQueue, ^{
-            // 等待上一次的操作完成
-            dispatch_semaphore_wait(self.volumeChangeSemaphore, DISPATCH_TIME_FOREVER);
-            self.stopChangeVolume = NO;
-            // 开始新的音量修改操作
-            AVAudioFramePosition startFrame = self.currentFrame;
-            NSLog(@"----- current frame -----%lld", startFrame);
-            [self modifyMixBuffer:self.bgBuffer bgBufferVolume:bgVolume withRecordBuffer:self.recordBuffer recordVolume:recordVolume offset:self.offsetTime startPosition:startFrame tagIndex:0];
-            // 释放信号量,标记音量修改操作完成
-            dispatch_semaphore_signal(self.volumeChangeSemaphore);
-        });
-    }
-}
-
-
-- (void)modifyMixBuffer:(AVAudioPCMBuffer *)bgBuffer bgBufferVolume:(float)bgBufferVolume withRecordBuffer:(AVAudioPCMBuffer *)recordBuffer recordVolume:(float)recordVolume offset:(NSInteger)offsetTime startPosition:(AVAudioFramePosition)startFrame tagIndex:(NSInteger)tagIndex {
-    
-    AVAudioFrameCount minFrameCount = MIN(bgBuffer.frameLength, recordBuffer.frameLength);
-    AVAudioFrameCount offsetFrame = labs(offsetTime)/1000.0 * recordBuffer.format.sampleRate;
-    
-    float *bgLeftChannel = bgBuffer.floatChannelData[0];
-    float *bgRightChannel = bgBuffer.floatChannelData[1];
-    // 录音文件未单声道
-    float *recordLeftChannel = recordBuffer.floatChannelData[0];
-    
-    float *mixLeftChannel = self.mixBuffer.floatChannelData[0];
-    float *mixRightChannel = self.mixBuffer.floatChannelData[1];
-    
-    // 先处理后续播放的buffer
-    NSLog(@"------- volume change start");
-    for (int frame = (int)startFrame; frame < minFrameCount; frame++) {
-        if (self.stopChangeVolume) {
-            NSLog(@"------- stop volume change");
-            dispatch_semaphore_signal(self.volumeChangeSemaphore); // 释放信号量
+        self.bgAudioFile.framePosition = startPosition;
+        AVAudioPCMBuffer *bgBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:self.bgAudioFile.processingFormat frameCapacity:frameToRead];
+        bgBuffer.frameLength = frameToRead;
+        BOOL readSuccess = [self.bgAudioFile readIntoBuffer:bgBuffer frameCount:frameToRead error:nil];
+        if (!readSuccess) {
             return;
         }
+        AVAudioPCMBuffer *recordBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:self.audioFile.processingFormat frameCapacity:frameToRead];
+        recordBuffer.frameLength = frameToRead;
         
-        float leftChannel = bgLeftChannel[frame];
-        float rightChannel = bgRightChannel[frame];
+        if (offsetTime >= 0) { // 演奏需要提前
+            self.audioFile.framePosition = startPosition + offsetFrame;
+            AVAudioFrameCount audioReadFrame = frameToRead;
+            if (startPosition + offsetFrame + frameToRead > minFrameCount) { // 如果超出
+                audioReadFrame = (AVAudioFrameCount)(minFrameCount - startPosition - offsetFrame);
+            }
+            if (audioReadFrame <= frameToRead) {
+                BOOL isSuccess = [self.audioFile readIntoBuffer:recordBuffer frameCount:audioReadFrame error:nil];
+                if (!isSuccess) {
+                    return;
+                }
+            }
+        }
+        else { // 演奏需要延后
+            AVAudioFramePosition audioFramePosition = startPosition - offsetFrame;
+            if (audioFramePosition > 0) {
+                self.audioFile.framePosition = audioFramePosition;
+                AVAudioFrameCount audioReadFrame = frameToRead;
+                if (audioFramePosition + frameToRead > minFrameCount) { // 如果超出
+                    audioReadFrame = (AVAudioFrameCount)(minFrameCount - audioFramePosition);
+                }
+                // AVAudioFrameCount 无符号整型 uint32_t
+                if (audioReadFrame <= frameToRead) {
+                    BOOL isSuccess = [self.audioFile readIntoBuffer:recordBuffer frameCount:audioReadFrame error:nil];
+                    if (!isSuccess) {
+                        return;
+                    }
+                }
+            }
+            else {
+                self.audioFile.framePosition = 0;
+                // 需要读取部分数据
+                if (offsetFrame - startPosition < frameToRead) {
+                    AVAudioFrameCount readCount = (AVAudioFrameCount)(offsetFrame - startPosition);
+//                    NSLog(@"----need readCount --%u", readCount);
+                    AVAudioPCMBuffer *tempBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:self.audioFile.processingFormat frameCapacity:readCount];
+                    tempBuffer.frameLength = readCount;
+                    BOOL isSuccess = [self.audioFile readIntoBuffer:tempBuffer error:nil];
+                    if (!isSuccess) {
+                        return;
+                    }
+                    float *tempData = tempBuffer.floatChannelData[0];
+                    float *recordData = recordBuffer.floatChannelData[0];
+                    // 复制数据到 recordBuffer
+                    AVAudioFrameCount startFrame = frameToRead - readCount;
+                    for (AVAudioFrameCount i = 0; i < readCount; i++) {
+                        recordData[startFrame + i] = tempData[i];
+                    }
+                }
+            }
+        }
         
-        int recordFrame = (offsetTime < 0) ? (frame - offsetFrame) : (frame + offsetFrame);
-        float recordData = (recordFrame >= 0 && recordFrame < recordBuffer.frameLength) ? recordLeftChannel[recordFrame] : 0;
+        float *bgLeftChannel = bgBuffer.floatChannelData[0];
+        float *bgRightChannel = bgBuffer.floatChannelData[1];
+        if (bgBuffer.format.channelCount == 1) {
+            bgRightChannel = bgBuffer.floatChannelData[0];
+        }
+        // 录音文件未单声道
+        float *recordLeftChannel = recordBuffer.floatChannelData[0];
         
-        float mixLeftData = [self mixChannelData:leftChannel bgVolume:bgBufferVolume recordData:recordData recordVolume:recordVolume];
-        float mixRightData = [self mixChannelData:rightChannel bgVolume:bgBufferVolume recordData:recordData recordVolume:recordVolume];
+        float *mixLeftChannel = self.mixBuffer.floatChannelData[0];
+        float *mixRightChannel = self.mixBuffer.floatChannelData[1];
         
-        mixLeftChannel[frame-self.startPosition] = MAX(-1.0, MIN(1.0, mixLeftData));
-        mixRightChannel[frame-self.startPosition] = MAX(-1.0, MIN(1.0, mixRightData));
-    }
-    NSLog(@"------- volume change end");
+        for (int frame = 0; frame < frameToRead; frame++) {
+            
+            AVAudioFramePosition mixIndex = frame + startPosition - mixStartPosition;
+            float leftChannel = (frame < bgBuffer.frameLength) ? bgLeftChannel[frame] : 0;
+            float rightChannel = (frame < bgBuffer.frameLength) ? bgRightChannel[frame] : 0;
+            
+            float recordData = (frame < recordBuffer.frameLength) ? recordLeftChannel[frame] : 0;
+            
+            float mixLeftData = [self mixChannelData:leftChannel bgVolume:self.bgVolume recordData:recordData recordVolume:self.recordVolume];
+            float mixRightData = [self mixChannelData:rightChannel bgVolume:self.bgVolume recordData:recordData recordVolume:self.recordVolume];
+            
+            // 防止数组越界
+            if (mixIndex >= 0 && mixIndex < self.mixBuffer.frameLength) {
+                mixLeftChannel[mixIndex] = fminf(fmaxf(mixLeftData, -1.0f), 1.0f);
+                mixRightChannel[mixIndex] = fminf(fmaxf(mixRightData, -1.0f), 1.0f);
+            }
+        }
+    });
 }
 
 - (void)scheduleBufferFromPosition:(AVAudioFramePosition)startPosition {
-    
-    self.stopMix = YES;
+    [self resetMixBuffer];
     self.startPosition = startPosition;
-    dispatch_async(self.sourceQueue, ^{
-        // 等待上一次的操作完成
-        dispatch_semaphore_wait(self.mixChangeSemaphore, DISPATCH_TIME_FOREVER);
-        self.stopMix = NO;
+    [self prepareBuffer:startPosition offset:self.offsetTime mixStart:startPosition];
+    // 加载缓冲区
+    [self.nodePlayer scheduleBuffer:self.mixBuffer atTime:nil options:AVAudioPlayerNodeBufferInterruptsAtLoop completionHandler:^{
         
-        [self mixBuffers:self.bgBuffer bgBufferVolume:self.bgVolume withRecordBuffer:self.recordBuffer recordVolume:self.recordVolume offset:self.offsetTime startPosition:(AVAudioFrameCount)startPosition];
-        // 释放信号量,标记修改操作完成
-        dispatch_semaphore_signal(self.mixChangeSemaphore);
-        // 加载缓冲区
-        [self.nodePlayer scheduleBuffer:self.mixBuffer atTime:nil options:AVAudioPlayerNodeBufferInterruptsAtLoop completionHandler:^{
-            
-        }];
-    });
+    }];
 }
 
 
 
+- (float)mixChannelData:(float)bgData bgVolume:(float)bgVolume recordData:(float)recordData recordVolume:(float)recordVolume {
+    return (bgData * bgVolume + recordData * recordVolume) / 2;
+}
+
+- (void)changeVolume:(float)bgVolume recordVolume:(float)recordVolume {
+//    NSLog(@"bg volume ---- %f,  record volume ---- %f", bgVolume, recordVolume);
+    self.bgVolume = bgVolume;
+    self.recordVolume = recordVolume;
+}
+
 // 打断处理
 - (void)handleInterruption:(NSNotification *)notification {
     NSDictionary *info = notification.userInfo;
@@ -386,6 +387,7 @@
         [self.delegate enginePlayerDidError:self error:error];
     }
 }
+
 #pragma mark ------ play action
 
 - (void)changeRecordDelay:(NSInteger)delayMs {
@@ -406,8 +408,7 @@
 }
 
 - (void)stopPlay {
-    self.stopMix = YES;
-    self.stopChangeVolume = YES;
+
     if (self.nodePlayer.isPlaying) {
         [self.nodePlayer stop];
     }
@@ -437,9 +438,6 @@
         }
     }
     
-    // 停止修改音量循环
-    self.stopChangeVolume = YES;
-    
     AVAudioFramePosition startFrame = startTime / 1000.0 * self.audioFormat.sampleRate;
     // 跳转进度
     self.currentFrame = startFrame;
@@ -459,15 +457,17 @@
 }
 
 - (void)freePlayer {
-    
-    if (self.nodePlayer.isPlaying) {
-        [self stopPlay];
-    }
+    [self stopPlay];
     [self.audioEngine stop];
+    // 停止并清理定时器
+    if (_timer) {
+        [_timer invalidate];
+        _timer = nil;
+    }
 }
 
 - (void)startTimer {
-    
+    self.timeCount = 0;
     [self.timer setFireDate:[NSDate distantPast]];
 }
 
@@ -488,7 +488,7 @@
     
     if (!_timer) {
         __weak typeof(self)weakSelf = self;
-        _timer = [NSTimer scheduledTimerWithTimeInterval:0.1 repeats:YES block:^(NSTimer * _Nonnull timer) {
+        _timer = [NSTimer scheduledTimerWithTimeInterval:0.01 repeats:YES block:^(NSTimer * _Nonnull timer) {
             [weakSelf timeFunction];
         }];
         [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
@@ -503,12 +503,18 @@
     float progress = currentTime/self.totalDuration;
     NSDate *date = [NSDate date];
     NSTimeInterval inteveral = [date timeIntervalSince1970];
-    if (currentTime > self.totalDuration) {
+    if (currentTime >= self.totalDuration) {
         if (self.delegate && [self.delegate respondsToSelector:@selector(enginePlayFinished:)]) {
             [self.delegate enginePlayFinished:self];
         }
     }
     else {
+        // 定时器10ms出触发一次 buffer每100ms执行一次
+        if (self.timeCount % 10 == 0) {
+            [self scheduleMixBuffer];
+        }
+        self.timeCount++;
+
         if (self.delegate && [self.delegate respondsToSelector:@selector(updatePlayProgress:andTotalTime:andProgress:currentInterval:inPlayer:)]) {
             [self.delegate updatePlayProgress:currentTime andTotalTime:self.totalDuration andProgress:progress currentInterval:inteveral*1000 inPlayer:self];
         }
@@ -516,6 +522,11 @@
     
 }
 
+- (void)scheduleMixBuffer {
+    if (self.nodePlayer.isPlaying) {
+        [self prepareBuffer:self.currentFrame offset:self.offsetTime mixStart:self.startPosition];
+    }
+}
 
 - (NSTimeInterval)getCurrentPlayTime {
     AVAudioTime *nodeTime = [self.nodePlayer lastRenderTime];
@@ -557,4 +568,10 @@
     }
     return NO;
 }
+
+- (void)dealloc {
+    NSLog(@"---- KSMergeEnginePlayer dealloc");
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
 @end

+ 8 - 2
KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/VideoPlayerView/KSVideoPlayerView.m

@@ -9,7 +9,6 @@
 #import <AVFoundation/AVFoundation.h>
 #import <CloudAccompanyLibrary/AVPlayer+KSSeekSmoothly.h>
 
-
 @interface KSVideoPlayerView ()
 
 @property (nonatomic, strong) AVPlayer *videoPlayer;
@@ -24,6 +23,8 @@
 
 @property (nonatomic, assign) BOOL hasFreeObserver;
 
+@property (nonatomic, assign) BOOL needResume; // 是否需要恢复播放
+
 @end
 
 @implementation KSVideoPlayerView
@@ -116,6 +117,7 @@
 }
 
 - (void)puasePlay {
+    self.needResume = NO;
     if (_isPlaying) {
         _isPlaying = NO;
         [_videoPlayer pause];
@@ -157,13 +159,17 @@
 - (void)seekOffsetTime:(NSInteger)offsetTime {
     CMTime newTime = CMTimeMake(offsetTime, 1000);
     CMTime toleranceTime = CMTimeMake(1, 1000);
+    if (self.isPlaying) {
+        self.needResume = YES;
+    }
     [self.videoPlayer pause];
     @weakObj(self);
     [self.videoPlayer ss_seekToTime:newTime toleranceBefore:toleranceTime toleranceAfter:toleranceTime completionHandler:^(BOOL finished) {
         @strongObj(self);
-        if (self.isPlaying) {
+        if (self.needResume) {
             [self.videoPlayer play];
         }
+        self.needResume = NO;
     }];
 }
 

+ 32 - 17
KulexiuForStudent/KulexiuForStudent/Module/Chat/Controller/TXCustom/KSTXBaseChatViewController.m

@@ -125,25 +125,40 @@ static UIView *gCustomTopView;
     }];
 }
 - (void)showMusic:(NSString *)songId {
-    PREMISSIONTYPE micEnable = [RecordCheckManager checkMicPermissionAvaiable];
-    PREMISSIONTYPE cameraEnable = [RecordCheckManager checkCameraPremissionAvaiable];
-    if (micEnable == PREMISSIONTYPE_YES && cameraEnable == PREMISSIONTYPE_YES) {
-        KSAccompanyWebViewController *detailCtrl = [[KSAccompanyWebViewController alloc] init];
-        detailCtrl.url = [NSString stringWithFormat:@"%@/accompany?id=%@",hostURL, songId];
-        detailCtrl.parmDic = @{@"isOpenLight" : @(YES), @"orientation" : @(0),@"isHideTitle" : @(YES)};
-        [self.navigationController pushViewController:detailCtrl animated:YES];
-    }
-    else {
-        if (micEnable == PREMISSIONTYPE_NO && cameraEnable == PREMISSIONTYPE_NO) { // 如果麦克风权限和摄像头权限都没有
-            [self showAlertWithMessage:@"请开启相机和麦克风访问权限" type:CHECKDEVICETYPE_BOTH];
-        }
-        else if (micEnable == PREMISSIONTYPE_NO) { // 如果没有麦克风权限
-            [self showAlertWithMessage:@"请开启麦克风访问权限" type:CHECKDEVICETYPE_MIC];
+    
+    [RecordCheckManager checkCameraPremissionAvaiableCallback:^(PREMISSIONTYPE type) {
+        [self afterCheckCameraCheckMic:type songId:songId];
+    }];
+}
+
+- (void)afterCheckCameraCheckMic:(PREMISSIONTYPE)cameraType songId:(NSString *)songId {
+    
+    [RecordCheckManager checkMicPermissionAvaiableCallback:^(PREMISSIONTYPE type) {
+        if (type == PREMISSIONTYPE_YES && cameraType == PREMISSIONTYPE_YES) {
+            KSAccompanyWebViewController *detailCtrl = [[KSAccompanyWebViewController alloc] init];
+            detailCtrl.url = [NSString stringWithFormat:@"%@/accompany?id=%@",hostURL, songId];
+            detailCtrl.parmDic = @{@"isOpenLight" : @(YES), @"orientation" : @(0),@"isHideTitle" : @(YES)};
+            [self.navigationController pushViewController:detailCtrl animated:YES];
         }
-        else if (cameraEnable == PREMISSIONTYPE_NO) { // 如果没有摄像头权限
-            [self showAlertWithMessage:@"请开启相机访问权限" type:CHECKDEVICETYPE_CAMREA];
+        else { //
+            
+            NSString *content = @"";
+            CHECKDEVICETYPE checkType = CHECKDEVICETYPE_BOTH;
+            if (cameraType == PREMISSIONTYPE_NO && type == PREMISSIONTYPE_NO) {
+                content = @"请开启相机和麦克风访问权限";
+                checkType = CHECKDEVICETYPE_BOTH;
+            }
+            else if (cameraType == PREMISSIONTYPE_NO && type == PREMISSIONTYPE_YES) {
+                content =  @"请开启相机访问权限";
+                checkType = CHECKDEVICETYPE_CAMREA;
+            }
+            else if (cameraType == PREMISSIONTYPE_YES && type == PREMISSIONTYPE_NO) {
+                content = @"请开启麦克风访问权限";
+                checkType = CHECKDEVICETYPE_MIC;
+            }
+            [self showAlertWithMessage:content type:checkType];
         }
-    }
+    }];
 }
 
 - (void)showAlertWithMessage:(NSString *)message type:(CHECKDEVICETYPE)deviceType {

+ 0 - 85
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/BassMidiEngine.h

@@ -1,85 +0,0 @@
-//
-//  BassMidiEngine.h
-//  StudentDaya
-//
-//  Created by Kyle on 2022/3/8.
-//  Copyright © 2022 DayaMusic. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-#import <AudioToolbox/AudioToolbox.h>
-#import <KSToolLibrary/CAudioUnit.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-@protocol BassMidiEngineDelegate <NSObject>
-
-/// 加载成功回调
-- (void)initEngineSuccess:(float)totalTime;
-
-/*    范围:[0,1],每10ms更新一次   */
-- (void)progressUpdated:(float)progress currentTime:(float)currentTime;
-
-/* 播放结束回调 */
-- (void)midiplayEnd;
-
-- (void)getMusicTotalTime:(float)totalTime;
-
-@end
-
-
-@interface BassMidiEngine : NSObject
-
-// 定义汇报进度频率 默认10ms
-@property (nonatomic, assign) NSInteger reportTime;
-// 每个track 对应的名称
-@property (nonatomic, strong) NSMutableArray *instrumentTrackNameArray;
-
-// 播放状态
-@property (nonatomic, assign) BOOL isPlaying;
-
-/* 选段播放控制 */
-
-// 选段的开始时间
-@property (nonatomic, assign) float startTime;
-// 选段的结束时间
-@property (nonatomic, assign) float endTime;
-
-/// 播放器回调delegate
-@property (nonatomic,weak)id<BassMidiEngineDelegate> delegate;
-
-
-- (void)configSoundFilePath:(NSString *)filePath;
-
-/*  加载MIDI文件  */
-- (BOOL)loadMIDIFileWithString:(NSString *)filePath;
-
-/* 播放器当前状态 */
-- (BOOL)isPlayingFile;
-/// 开始播放
-- (void)startPlay;
-/// 停止播放
-- (void)stopPlay;
-
-/// 释放引擎
-- (void)freeEngine;
-
-/*  设置播放速度,快播:(1,+∞),慢放:(0,1)   */
-- (BOOL)setMusicPlayerSpeed:(float)speed;
-
-/* 设置播放的进度开始时间  */
-- (void)setProgressTime:(MusicTimeStamp)startTime;
-
-/*  調節某一軌的音量  範圍:[0,1] */
-- (void)volume:(float)volume WithTrack:(UInt32)trackNum;
-
-#pragma mark ------ 变调 调整hz
-// 转成442HZ播放
-- (void)transformTo442Hz;
-
-// hz调整 440 - 442。。。。。。。
-- (void)adjustPitchByHZ:(float)newHZ;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 186
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/BassMidiEngine.m

@@ -1,186 +0,0 @@
-//
-//  BassMidiEngine.m
-//  StudentDaya
-//
-//  Created by Kyle on 2022/3/8.
-//  Copyright © 2022 DayaMusic. All rights reserved.
-//
-
-#import "BassMidiEngine.h"
-#import "bass.h"
-#import "bassmidi.h"
-#import <AVFoundation/AVFoundation.h>
-#import <KSToolLibrary/GCDTimer.h>
-
-@interface BassMidiEngine ()
-{
-    HSTREAM _stream;
-}
-@property (nonatomic, strong) NSString *soundFileUrl;
-
-@property (nonatomic, strong) NSString *midFilePath;
-
-
-
-@end
-
-@implementation BassMidiEngine
-
-- (instancetype)init {
-    self = [super init];
-    if (self) {
-        [self configDefault];
-    }
-    return self;
-}
-
-- (void)configDefault {
-    self.soundFileUrl = [[NSBundle mainBundle]
-                         pathForResource:@"synthgms" ofType:@"sf2"];
-    [self setupAudioSession];
-}
-
-- (void)setupAudioSession {
-    
-    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
-    NSError *err = nil;
-    AVAudioSessionCategory category = AVAudioSessionCategoryPlayAndRecord;
-    if (@available(iOS 10.0, *)) {
-        [audioSession setCategory:category mode:AVAudioSessionModeDefault options:AVAudioSessionCategoryOptionAllowBluetooth|AVAudioSessionCategoryOptionAllowBluetoothA2DP|AVAudioSessionCategoryOptionDefaultToSpeaker|AVAudioSessionCategoryOptionMixWithOthers error:&err];
-    }
-    else {
-        [audioSession setCategory:category withOptions:AVAudioSessionCategoryOptionAllowBluetooth|AVAudioSessionCategoryOptionDefaultToSpeaker|AVAudioSessionCategoryOptionMixWithOthers error:&err];
-    }
-    [audioSession setActive:YES error:&err];
-}
-
-- (void)configSoundFilePath:(NSString *)filePath {
-    self.soundFileUrl = filePath;
-}
-
-- (BOOL)setupEngineWithFile:(NSString *)filePath {
-    //BASS init
-    BASS_Init(-1, 44100, 0, 0, NULL);
-    _stream = BASS_MIDI_StreamCreateFile(FALSE, [filePath UTF8String], 0, 0, 0, 44100);
-    if (BASS_ErrorGetCode()) {
-        NSLog(@"Bass error: %i", BASS_ErrorGetCode());
-        return NO;
-    }
-    // set font
-    BASS_MIDI_FONT font = [self getBassMidiFont];
-    BASS_MIDI_StreamSetFonts(_stream, &font, 1);
-    
-    return YES;
-}
-
-- (BASS_MIDI_FONT)getBassMidiFont {
-    BASS_MIDI_FONT midiFont;
-    midiFont.font = BASS_MIDI_FontInit([self.soundFileUrl UTF8String], 0);
-    midiFont.preset = -1;
-    midiFont.bank = 0;
-    return midiFont;
-}
-
-- (BOOL)loadMIDIFileWithString:(NSString *)filePath {
-    // 判断文件是否存在
-    BOOL isExist = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
-    if (isExist) {
-        return [self setupEngineWithFile:filePath];
-    }
-    else {
-        NSLog(@"文件不存在 !!!");
-        return NO;
-    }
-}
-
-
-- (BOOL)isPlayingFile {
-    if (_stream == 0) {
-        return NO;
-    }
-    //    0 - BASS_ACTIVE_STOPPED   The channel is not active, or handle is not a valid channel.
-    //    1 - BASS_ACTIVE_PLAYING   The channel is playing (or recording).
-    //    2 - BASS_ACTIVE_PAUSED    The channel is paused.
-    //    3 - BASS_ACTIVE_STALLED   Playback of the stream has been stalled due to a lack of sample data.
-    //                              The playback will automatically resume once there is sufficient data to do so.
-    int status = BASS_ChannelIsActive(_stream);
-    switch (status) {
-        case BASS_ACTIVE_STOPPED: // 停止
-        {
-            
-        }
-            break;
-        case BASS_ACTIVE_PLAYING: // 播放中
-        {
-            
-        }
-            break;
-        case BASS_ACTIVE_PAUSED:
-        case BASS_ACTIVE_STALLED:
-        {
-            
-        }
-            break;
-        default:
-            break;
-    }
-    if (status == 1) {
-        return YES;
-    }
-    else {
-        return NO;
-    }
-}
-
-- (void)startPlay {
-    if (_stream == 0) {
-        // 未初始化stream
-        return;
-    }
-    if (self.isPlaying) {
-        [self stopPlay];
-    }
-    
-    BASS_ChannelPlay(_stream, 0);
-    self.isPlaying = YES;
-    NSLog(@"testMidiFile complete");
-    __weak typeof(self) weakSelf = self;
-    dispatch_queue_t queue = dispatch_queue_create("BassPlayerTimer", DISPATCH_QUEUE_SERIAL);
-    [[GCDTimer shared] scheduleGCDTimerWithName:@"BassMusicPlayerTimer" Interval:self.reportTime Queue:queue Repeats:YES Action:^{
-            
-        // 获取当前进度
-        
-    }];
-    
-}
-
-- (void)stopPlay {
-    BASS_ChannelStop(_stream);
-    self.isPlaying = NO;
-    [[GCDTimer shared] cancelAllTimer];
-}
-
-- (BOOL)setMusicPlayerSpeed:(float)speed {
-    BOOL isSuccess = BASS_ChannelSetAttribute(_stream, BASS_ATTRIB_MIDI_SPEED, speed);
-    return isSuccess;
-}
-
-/// 释放引擎
-- (void)freeEngine {
-    if (_stream) {
-        BASS_ChannelFree(_stream);
-    }
-}
-
-#pragma mark ------ 变调 调整hz
-// 转成442HZ播放
-- (void)transformTo442Hz {
-    
-}
-
-// hz调整 440 - 442。。。。。。。
-- (void)adjustPitchByHZ:(float)newHZ {
-    
-}
-
-@end

+ 0 - 1131
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bass.h

@@ -1,1131 +0,0 @@
-/*
-	BASS 2.4 C/C++ header file
-	Copyright (c) 1999-2021 Un4seen Developments Ltd.
-
-	See the BASS.CHM file for more detailed documentation
-*/
-
-#ifndef BASS_H
-#define BASS_H
-
-#ifdef _WIN32
-#ifdef WINAPI_FAMILY
-#include <winapifamily.h>
-#endif
-#include <wtypes.h>
-typedef unsigned __int64 QWORD;
-#else
-#include <stdint.h>
-#define WINAPI
-#define CALLBACK
-typedef uint8_t BYTE;
-typedef uint16_t WORD;
-typedef uint32_t DWORD;
-typedef uint64_t QWORD;
-#ifdef __OBJC__
-typedef int BOOL32;
-#define BOOL BOOL32 // override objc's BOOL
-#else
-typedef int BOOL;
-#endif
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#endif
-#define LOBYTE(a) (BYTE)(a)
-#define HIBYTE(a) (BYTE)((a)>>8)
-#define LOWORD(a) (WORD)(a)
-#define HIWORD(a) (WORD)((a)>>16)
-#define MAKEWORD(a,b) (WORD)(((a)&0xff)|((b)<<8))
-#define MAKELONG(a,b) (DWORD)(((a)&0xffff)|((b)<<16))
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define BASSVERSION			0x204	// API version
-#define BASSVERSIONTEXT		"2.4"
-
-#ifndef BASSDEF
-#define BASSDEF(f) WINAPI f
-#else
-#define NOBASSOVERLOADS
-#endif
-
-typedef DWORD HMUSIC;		// MOD music handle
-typedef DWORD HSAMPLE;		// sample handle
-typedef DWORD HCHANNEL;		// sample playback handle
-typedef DWORD HSTREAM;		// sample stream handle
-typedef DWORD HRECORD;		// recording handle
-typedef DWORD HSYNC;		// synchronizer handle
-typedef DWORD HDSP;			// DSP handle
-typedef DWORD HFX;			// effect handle
-typedef DWORD HPLUGIN;		// plugin handle
-
-// Error codes returned by BASS_ErrorGetCode
-#define BASS_OK				0	// all is OK
-#define BASS_ERROR_MEM		1	// memory error
-#define BASS_ERROR_FILEOPEN	2	// can't open the file
-#define BASS_ERROR_DRIVER	3	// can't find a free/valid driver
-#define BASS_ERROR_BUFLOST	4	// the sample buffer was lost
-#define BASS_ERROR_HANDLE	5	// invalid handle
-#define BASS_ERROR_FORMAT	6	// unsupported sample format
-#define BASS_ERROR_POSITION	7	// invalid position
-#define BASS_ERROR_INIT		8	// BASS_Init has not been successfully called
-#define BASS_ERROR_START	9	// BASS_Start has not been successfully called
-#define BASS_ERROR_SSL		10	// SSL/HTTPS support isn't available
-#define BASS_ERROR_REINIT	11	// device needs to be reinitialized
-#define BASS_ERROR_ALREADY	14	// already initialized/paused/whatever
-#define BASS_ERROR_NOTAUDIO	17	// file does not contain audio
-#define BASS_ERROR_NOCHAN	18	// can't get a free channel
-#define BASS_ERROR_ILLTYPE	19	// an illegal type was specified
-#define BASS_ERROR_ILLPARAM	20	// an illegal parameter was specified
-#define BASS_ERROR_NO3D		21	// no 3D support
-#define BASS_ERROR_NOEAX	22	// no EAX support
-#define BASS_ERROR_DEVICE	23	// illegal device number
-#define BASS_ERROR_NOPLAY	24	// not playing
-#define BASS_ERROR_FREQ		25	// illegal sample rate
-#define BASS_ERROR_NOTFILE	27	// the stream is not a file stream
-#define BASS_ERROR_NOHW		29	// no hardware voices available
-#define BASS_ERROR_EMPTY	31	// the MOD music has no sequence data
-#define BASS_ERROR_NONET	32	// no internet connection could be opened
-#define BASS_ERROR_CREATE	33	// couldn't create the file
-#define BASS_ERROR_NOFX		34	// effects are not available
-#define BASS_ERROR_NOTAVAIL	37	// requested data/action is not available
-#define BASS_ERROR_DECODE	38	// the channel is/isn't a "decoding channel"
-#define BASS_ERROR_DX		39	// a sufficient DirectX version is not installed
-#define BASS_ERROR_TIMEOUT	40	// connection timedout
-#define BASS_ERROR_FILEFORM	41	// unsupported file format
-#define BASS_ERROR_SPEAKER	42	// unavailable speaker
-#define BASS_ERROR_VERSION	43	// invalid BASS version (used by add-ons)
-#define BASS_ERROR_CODEC	44	// codec is not available/supported
-#define BASS_ERROR_ENDED	45	// the channel/file has ended
-#define BASS_ERROR_BUSY		46	// the device is busy
-#define BASS_ERROR_UNSTREAMABLE	47	// unstreamable file
-#define BASS_ERROR_PROTOCOL	48	// unsupported protocol
-#define BASS_ERROR_UNKNOWN	-1	// some other mystery problem
-
-// BASS_SetConfig options
-#define BASS_CONFIG_BUFFER			0
-#define BASS_CONFIG_UPDATEPERIOD	1
-#define BASS_CONFIG_GVOL_SAMPLE		4
-#define BASS_CONFIG_GVOL_STREAM		5
-#define BASS_CONFIG_GVOL_MUSIC		6
-#define BASS_CONFIG_CURVE_VOL		7
-#define BASS_CONFIG_CURVE_PAN		8
-#define BASS_CONFIG_FLOATDSP		9
-#define BASS_CONFIG_3DALGORITHM		10
-#define BASS_CONFIG_NET_TIMEOUT		11
-#define BASS_CONFIG_NET_BUFFER		12
-#define BASS_CONFIG_PAUSE_NOPLAY	13
-#define BASS_CONFIG_NET_PREBUF		15
-#define BASS_CONFIG_NET_PASSIVE		18
-#define BASS_CONFIG_REC_BUFFER		19
-#define BASS_CONFIG_NET_PLAYLIST	21
-#define BASS_CONFIG_MUSIC_VIRTUAL	22
-#define BASS_CONFIG_VERIFY			23
-#define BASS_CONFIG_UPDATETHREADS	24
-#define BASS_CONFIG_DEV_BUFFER		27
-#define BASS_CONFIG_REC_LOOPBACK	28
-#define BASS_CONFIG_VISTA_TRUEPOS	30
-#define BASS_CONFIG_IOS_SESSION		34
-#define BASS_CONFIG_IOS_MIXAUDIO	34
-#define BASS_CONFIG_DEV_DEFAULT		36
-#define BASS_CONFIG_NET_READTIMEOUT	37
-#define BASS_CONFIG_VISTA_SPEAKERS	38
-#define BASS_CONFIG_IOS_SPEAKER		39
-#define BASS_CONFIG_MF_DISABLE		40
-#define BASS_CONFIG_HANDLES			41
-#define BASS_CONFIG_UNICODE			42
-#define BASS_CONFIG_SRC				43
-#define BASS_CONFIG_SRC_SAMPLE		44
-#define BASS_CONFIG_ASYNCFILE_BUFFER 45
-#define BASS_CONFIG_OGG_PRESCAN		47
-#define BASS_CONFIG_MF_VIDEO		48
-#define BASS_CONFIG_AIRPLAY			49
-#define BASS_CONFIG_DEV_NONSTOP		50
-#define BASS_CONFIG_IOS_NOCATEGORY	51
-#define BASS_CONFIG_VERIFY_NET		52
-#define BASS_CONFIG_DEV_PERIOD		53
-#define BASS_CONFIG_FLOAT			54
-#define BASS_CONFIG_NET_SEEK		56
-#define BASS_CONFIG_AM_DISABLE		58
-#define BASS_CONFIG_NET_PLAYLIST_DEPTH	59
-#define BASS_CONFIG_NET_PREBUF_WAIT	60
-#define BASS_CONFIG_ANDROID_SESSIONID	62
-#define BASS_CONFIG_WASAPI_PERSIST	65
-#define BASS_CONFIG_REC_WASAPI		66
-#define BASS_CONFIG_ANDROID_AAUDIO	67
-#define BASS_CONFIG_SAMPLE_ONEHANDLE	69
-#define BASS_CONFIG_DEV_TIMEOUT		70
-#define BASS_CONFIG_NET_META		71
-#define BASS_CONFIG_NET_RESTRATE	72
-
-// BASS_SetConfigPtr options
-#define BASS_CONFIG_NET_AGENT		16
-#define BASS_CONFIG_NET_PROXY		17
-#define BASS_CONFIG_IOS_NOTIFY		46
-#define BASS_CONFIG_LIBSSL			64
-
-#define BASS_CONFIG_THREAD			0x40000000 // flag: thread-specific setting
-
-// BASS_CONFIG_IOS_SESSION flags
-#define BASS_IOS_SESSION_MIX		1
-#define BASS_IOS_SESSION_DUCK		2
-#define BASS_IOS_SESSION_AMBIENT	4
-#define BASS_IOS_SESSION_SPEAKER	8
-#define BASS_IOS_SESSION_DISABLE	16
-
-// BASS_Init flags
-#define BASS_DEVICE_8BITS		1		// unused
-#define BASS_DEVICE_MONO		2		// mono
-#define BASS_DEVICE_3D			4		// unused
-#define BASS_DEVICE_16BITS		8		// limit output to 16-bit
-#define BASS_DEVICE_REINIT		128		// reinitialize
-#define BASS_DEVICE_LATENCY		0x100	// unused
-#define BASS_DEVICE_CPSPEAKERS	0x400	// unused
-#define BASS_DEVICE_SPEAKERS	0x800	// force enabling of speaker assignment
-#define BASS_DEVICE_NOSPEAKER	0x1000	// ignore speaker arrangement
-#define BASS_DEVICE_DMIX		0x2000	// use ALSA "dmix" plugin
-#define BASS_DEVICE_FREQ		0x4000	// set device sample rate
-#define BASS_DEVICE_STEREO		0x8000	// limit output to stereo
-#define BASS_DEVICE_HOG			0x10000	// hog/exclusive mode
-#define BASS_DEVICE_AUDIOTRACK	0x20000	// use AudioTrack output
-#define BASS_DEVICE_DSOUND		0x40000	// use DirectSound output
-#define BASS_DEVICE_SOFTWARE	0x80000	// disable hardware/fastpath output
-
-// DirectSound interfaces (for use with BASS_GetDSoundObject)
-#define BASS_OBJECT_DS		1	// IDirectSound
-#define BASS_OBJECT_DS3DL	2	// IDirectSound3DListener
-
-// Device info structure
-typedef struct {
-#if defined(_WIN32_WCE) || (defined(WINAPI_FAMILY) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
-	const wchar_t *name;	// description
-	const wchar_t *driver;	// driver
-#else
-	const char *name;	// description
-	const char *driver;	// driver
-#endif
-	DWORD flags;
-} BASS_DEVICEINFO;
-
-// BASS_DEVICEINFO flags
-#define BASS_DEVICE_ENABLED		1
-#define BASS_DEVICE_DEFAULT		2
-#define BASS_DEVICE_INIT		4
-#define BASS_DEVICE_LOOPBACK	8
-#define BASS_DEVICE_DEFAULTCOM	128
-
-#define BASS_DEVICE_TYPE_MASK			0xff000000
-#define BASS_DEVICE_TYPE_NETWORK		0x01000000
-#define BASS_DEVICE_TYPE_SPEAKERS		0x02000000
-#define BASS_DEVICE_TYPE_LINE			0x03000000
-#define BASS_DEVICE_TYPE_HEADPHONES		0x04000000
-#define BASS_DEVICE_TYPE_MICROPHONE		0x05000000
-#define BASS_DEVICE_TYPE_HEADSET		0x06000000
-#define BASS_DEVICE_TYPE_HANDSET		0x07000000
-#define BASS_DEVICE_TYPE_DIGITAL		0x08000000
-#define BASS_DEVICE_TYPE_SPDIF			0x09000000
-#define BASS_DEVICE_TYPE_HDMI			0x0a000000
-#define BASS_DEVICE_TYPE_DISPLAYPORT	0x40000000
-
-// BASS_GetDeviceInfo flags
-#define BASS_DEVICES_AIRPLAY	0x1000000
-
-typedef struct {
-	DWORD flags;	// device capabilities (DSCAPS_xxx flags)
-	DWORD hwsize;	// unused
-	DWORD hwfree;	// unused
-	DWORD freesam;	// unused
-	DWORD free3d;	// unused
-	DWORD minrate;	// unused
-	DWORD maxrate;	// unused
-	BOOL eax;		// unused
-	DWORD minbuf;	// recommended minimum buffer length in ms
-	DWORD dsver;	// DirectSound version
-	DWORD latency;	// average delay (in ms) before start of playback
-	DWORD initflags; // BASS_Init "flags" parameter
-	DWORD speakers; // number of speakers available
-	DWORD freq;		// current output rate
-} BASS_INFO;
-
-// BASS_INFO flags (from DSOUND.H)
-#define DSCAPS_EMULDRIVER		0x00000020	// device does not have hardware DirectSound support
-#define DSCAPS_CERTIFIED		0x00000040	// device driver has been certified by Microsoft
-
-#define DSCAPS_HARDWARE			0x80000000	// hardware mixed
-
-// Recording device info structure
-typedef struct {
-	DWORD flags;	// device capabilities (DSCCAPS_xxx flags)
-	DWORD formats;	// supported standard formats (WAVE_FORMAT_xxx flags)
-	DWORD inputs;	// number of inputs
-	BOOL singlein;	// TRUE = only 1 input can be set at a time
-	DWORD freq;		// current input rate
-} BASS_RECORDINFO;
-
-// BASS_RECORDINFO flags (from DSOUND.H)
-#define DSCCAPS_EMULDRIVER		DSCAPS_EMULDRIVER	// device does not have hardware DirectSound recording support
-#define DSCCAPS_CERTIFIED		DSCAPS_CERTIFIED	// device driver has been certified by Microsoft
-
-// defines for formats field of BASS_RECORDINFO (from MMSYSTEM.H)
-#ifndef WAVE_FORMAT_1M08
-#define WAVE_FORMAT_1M08       0x00000001       /* 11.025 kHz, Mono,   8-bit  */
-#define WAVE_FORMAT_1S08       0x00000002       /* 11.025 kHz, Stereo, 8-bit  */
-#define WAVE_FORMAT_1M16       0x00000004       /* 11.025 kHz, Mono,   16-bit */
-#define WAVE_FORMAT_1S16       0x00000008       /* 11.025 kHz, Stereo, 16-bit */
-#define WAVE_FORMAT_2M08       0x00000010       /* 22.05  kHz, Mono,   8-bit  */
-#define WAVE_FORMAT_2S08       0x00000020       /* 22.05  kHz, Stereo, 8-bit  */
-#define WAVE_FORMAT_2M16       0x00000040       /* 22.05  kHz, Mono,   16-bit */
-#define WAVE_FORMAT_2S16       0x00000080       /* 22.05  kHz, Stereo, 16-bit */
-#define WAVE_FORMAT_4M08       0x00000100       /* 44.1   kHz, Mono,   8-bit  */
-#define WAVE_FORMAT_4S08       0x00000200       /* 44.1   kHz, Stereo, 8-bit  */
-#define WAVE_FORMAT_4M16       0x00000400       /* 44.1   kHz, Mono,   16-bit */
-#define WAVE_FORMAT_4S16       0x00000800       /* 44.1   kHz, Stereo, 16-bit */
-#endif
-
-// Sample info structure
-typedef struct {
-	DWORD freq;		// default playback rate
-	float volume;	// default volume (0-1)
-	float pan;		// default pan (-1=left, 0=middle, 1=right)
-	DWORD flags;	// BASS_SAMPLE_xxx flags
-	DWORD length;	// length (in bytes)
-	DWORD max;		// maximum simultaneous playbacks
-	DWORD origres;	// original resolution
-	DWORD chans;	// number of channels
-	DWORD mingap;	// minimum gap (ms) between creating channels
-	DWORD mode3d;	// BASS_3DMODE_xxx mode
-	float mindist;	// minimum distance
-	float maxdist;	// maximum distance
-	DWORD iangle;	// angle of inside projection cone
-	DWORD oangle;	// angle of outside projection cone
-	float outvol;	// delta-volume outside the projection cone
-	DWORD vam;		// unused
-	DWORD priority;	// unused
-} BASS_SAMPLE;
-
-#define BASS_SAMPLE_8BITS		1	// 8 bit
-#define BASS_SAMPLE_FLOAT		256	// 32 bit floating-point
-#define BASS_SAMPLE_MONO		2	// mono
-#define BASS_SAMPLE_LOOP		4	// looped
-#define BASS_SAMPLE_3D			8	// 3D functionality
-#define BASS_SAMPLE_SOFTWARE	16	// unused
-#define BASS_SAMPLE_MUTEMAX		32	// mute at max distance (3D only)
-#define BASS_SAMPLE_VAM			64	// unused
-#define BASS_SAMPLE_FX			128	// unused
-#define BASS_SAMPLE_OVER_VOL	0x10000	// override lowest volume
-#define BASS_SAMPLE_OVER_POS	0x20000	// override longest playing
-#define BASS_SAMPLE_OVER_DIST	0x30000 // override furthest from listener (3D only)
-
-#define BASS_STREAM_PRESCAN		0x20000 // scan file for accurate seeking and length
-#define BASS_STREAM_AUTOFREE	0x40000	// automatically free the stream when it stops/ends
-#define BASS_STREAM_RESTRATE	0x80000	// restrict the download rate of internet file stream
-#define BASS_STREAM_BLOCK		0x100000 // download internet file stream in small blocks
-#define BASS_STREAM_DECODE		0x200000 // don't play the stream, only decode
-#define BASS_STREAM_STATUS		0x800000 // give server status info (HTTP/ICY tags) in DOWNLOADPROC
-
-#define BASS_MP3_IGNOREDELAY	0x200 // ignore LAME/Xing/VBRI/iTunes delay & padding info
-#define BASS_MP3_SETPOS			BASS_STREAM_PRESCAN
-
-#define BASS_MUSIC_FLOAT		BASS_SAMPLE_FLOAT
-#define BASS_MUSIC_MONO			BASS_SAMPLE_MONO
-#define BASS_MUSIC_LOOP			BASS_SAMPLE_LOOP
-#define BASS_MUSIC_3D			BASS_SAMPLE_3D
-#define BASS_MUSIC_FX			BASS_SAMPLE_FX
-#define BASS_MUSIC_AUTOFREE		BASS_STREAM_AUTOFREE
-#define BASS_MUSIC_DECODE		BASS_STREAM_DECODE
-#define BASS_MUSIC_PRESCAN		BASS_STREAM_PRESCAN	// calculate playback length
-#define BASS_MUSIC_CALCLEN		BASS_MUSIC_PRESCAN
-#define BASS_MUSIC_RAMP			0x200	// normal ramping
-#define BASS_MUSIC_RAMPS		0x400	// sensitive ramping
-#define BASS_MUSIC_SURROUND		0x800	// surround sound
-#define BASS_MUSIC_SURROUND2	0x1000	// surround sound (mode 2)
-#define BASS_MUSIC_FT2PAN		0x2000	// apply FastTracker 2 panning to XM files
-#define BASS_MUSIC_FT2MOD		0x2000	// play .MOD as FastTracker 2 does
-#define BASS_MUSIC_PT1MOD		0x4000	// play .MOD as ProTracker 1 does
-#define BASS_MUSIC_NONINTER		0x10000	// non-interpolated sample mixing
-#define BASS_MUSIC_SINCINTER	0x800000 // sinc interpolated sample mixing
-#define BASS_MUSIC_POSRESET		0x8000	// stop all notes when moving position
-#define BASS_MUSIC_POSRESETEX	0x400000 // stop all notes and reset bmp/etc when moving position
-#define BASS_MUSIC_STOPBACK		0x80000	// stop the music on a backwards jump effect
-#define BASS_MUSIC_NOSAMPLE		0x100000 // don't load the samples
-
-// Speaker assignment flags
-#define BASS_SPEAKER_FRONT	0x1000000	// front speakers
-#define BASS_SPEAKER_REAR	0x2000000	// rear/side speakers
-#define BASS_SPEAKER_CENLFE	0x3000000	// center & LFE speakers (5.1)
-#define BASS_SPEAKER_REAR2	0x4000000	// rear center speakers (7.1)
-#define BASS_SPEAKER_N(n)	((n)<<24)	// n'th pair of speakers (max 15)
-#define BASS_SPEAKER_LEFT	0x10000000	// modifier: left
-#define BASS_SPEAKER_RIGHT	0x20000000	// modifier: right
-#define BASS_SPEAKER_FRONTLEFT	BASS_SPEAKER_FRONT|BASS_SPEAKER_LEFT
-#define BASS_SPEAKER_FRONTRIGHT	BASS_SPEAKER_FRONT|BASS_SPEAKER_RIGHT
-#define BASS_SPEAKER_REARLEFT	BASS_SPEAKER_REAR|BASS_SPEAKER_LEFT
-#define BASS_SPEAKER_REARRIGHT	BASS_SPEAKER_REAR|BASS_SPEAKER_RIGHT
-#define BASS_SPEAKER_CENTER		BASS_SPEAKER_CENLFE|BASS_SPEAKER_LEFT
-#define BASS_SPEAKER_LFE		BASS_SPEAKER_CENLFE|BASS_SPEAKER_RIGHT
-#define BASS_SPEAKER_REAR2LEFT	BASS_SPEAKER_REAR2|BASS_SPEAKER_LEFT
-#define BASS_SPEAKER_REAR2RIGHT	BASS_SPEAKER_REAR2|BASS_SPEAKER_RIGHT
-
-#define BASS_ASYNCFILE			0x40000000	// read file asynchronously
-#define BASS_UNICODE			0x80000000	// UTF-16
-
-#define BASS_RECORD_PAUSE		0x8000	// start recording paused
-#define BASS_RECORD_ECHOCANCEL	0x2000
-#define BASS_RECORD_AGC			0x4000
-
-// DX7 voice allocation & management flags
-#define BASS_VAM_HARDWARE		1
-#define BASS_VAM_SOFTWARE		2
-#define BASS_VAM_TERM_TIME		4
-#define BASS_VAM_TERM_DIST		8
-#define BASS_VAM_TERM_PRIO		16
-
-// Channel info structure
-typedef struct {
-	DWORD freq;		// default playback rate
-	DWORD chans;	// channels
-	DWORD flags;
-	DWORD ctype;	// type of channel
-	DWORD origres;	// original resolution
-	HPLUGIN plugin;
-	HSAMPLE sample;
-	const char *filename;
-} BASS_CHANNELINFO;
-
-#define BASS_ORIGRES_FLOAT		0x10000
-
-// BASS_CHANNELINFO types
-#define BASS_CTYPE_SAMPLE		1
-#define BASS_CTYPE_RECORD		2
-#define BASS_CTYPE_STREAM		0x10000
-#define BASS_CTYPE_STREAM_VORBIS	0x10002
-#define BASS_CTYPE_STREAM_OGG	0x10002
-#define BASS_CTYPE_STREAM_MP1	0x10003
-#define BASS_CTYPE_STREAM_MP2	0x10004
-#define BASS_CTYPE_STREAM_MP3	0x10005
-#define BASS_CTYPE_STREAM_AIFF	0x10006
-#define BASS_CTYPE_STREAM_CA	0x10007
-#define BASS_CTYPE_STREAM_MF	0x10008
-#define BASS_CTYPE_STREAM_AM	0x10009
-#define BASS_CTYPE_STREAM_SAMPLE	0x1000a
-#define BASS_CTYPE_STREAM_DUMMY		0x18000
-#define BASS_CTYPE_STREAM_DEVICE	0x18001
-#define BASS_CTYPE_STREAM_WAV	0x40000 // WAVE flag (LOWORD=codec)
-#define BASS_CTYPE_STREAM_WAV_PCM	0x50001
-#define BASS_CTYPE_STREAM_WAV_FLOAT	0x50003
-#define BASS_CTYPE_MUSIC_MOD	0x20000
-#define BASS_CTYPE_MUSIC_MTM	0x20001
-#define BASS_CTYPE_MUSIC_S3M	0x20002
-#define BASS_CTYPE_MUSIC_XM		0x20003
-#define BASS_CTYPE_MUSIC_IT		0x20004
-#define BASS_CTYPE_MUSIC_MO3	0x00100 // MO3 flag
-
-typedef struct {
-	DWORD ctype;		// channel type
-#if defined(_WIN32_WCE) || (defined(WINAPI_FAMILY) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
-	const wchar_t *name;	// format description
-	const wchar_t *exts;	// file extension filter (*.ext1;*.ext2;etc...)
-#else
-	const char *name;	// format description
-	const char *exts;	// file extension filter (*.ext1;*.ext2;etc...)
-#endif
-} BASS_PLUGINFORM;
-
-typedef struct {
-	DWORD version;					// version (same form as BASS_GetVersion)
-	DWORD formatc;					// number of formats
-	const BASS_PLUGINFORM *formats;	// the array of formats
-} BASS_PLUGININFO;
-
-// 3D vector (for 3D positions/velocities/orientations)
-typedef struct BASS_3DVECTOR {
-#ifdef __cplusplus
-	BASS_3DVECTOR() {};
-	BASS_3DVECTOR(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {};
-#endif
-	float x;	// +=right, -=left
-	float y;	// +=up, -=down
-	float z;	// +=front, -=behind
-} BASS_3DVECTOR;
-
-// 3D channel modes
-#define BASS_3DMODE_NORMAL		0	// normal 3D processing
-#define BASS_3DMODE_RELATIVE	1	// position is relative to the listener
-#define BASS_3DMODE_OFF			2	// no 3D processing
-
-// software 3D mixing algorithms (used with BASS_CONFIG_3DALGORITHM)
-#define BASS_3DALG_DEFAULT	0
-#define BASS_3DALG_OFF		1
-#define BASS_3DALG_FULL		2
-#define BASS_3DALG_LIGHT	3
-
-// BASS_SampleGetChannel flags
-#define BASS_SAMCHAN_NEW		1	// get a new playback channel
-#define BASS_SAMCHAN_STREAM		2	// create a stream
-
-typedef DWORD (CALLBACK STREAMPROC)(HSTREAM handle, void *buffer, DWORD length, void *user);
-/* User stream callback function.
-handle : The stream that needs writing
-buffer : Buffer to write the samples in
-length : Number of bytes to write
-user   : The 'user' parameter value given when calling BASS_StreamCreate
-RETURN : Number of bytes written. Set the BASS_STREAMPROC_END flag to end the stream. */
-
-#define BASS_STREAMPROC_END		0x80000000	// end of user stream flag
-
-// Special STREAMPROCs
-#define STREAMPROC_DUMMY		(STREAMPROC*)0		// "dummy" stream
-#define STREAMPROC_PUSH			(STREAMPROC*)-1		// push stream
-#define STREAMPROC_DEVICE		(STREAMPROC*)-2		// device mix stream
-#define STREAMPROC_DEVICE_3D	(STREAMPROC*)-3		// device 3D mix stream
-
-// BASS_StreamCreateFileUser file systems
-#define STREAMFILE_NOBUFFER		0
-#define STREAMFILE_BUFFER		1
-#define STREAMFILE_BUFFERPUSH	2
-
-// User file stream callback functions
-typedef void (CALLBACK FILECLOSEPROC)(void *user);
-typedef QWORD (CALLBACK FILELENPROC)(void *user);
-typedef DWORD (CALLBACK FILEREADPROC)(void *buffer, DWORD length, void *user);
-typedef BOOL (CALLBACK FILESEEKPROC)(QWORD offset, void *user);
-
-typedef struct {
-	FILECLOSEPROC *close;
-	FILELENPROC *length;
-	FILEREADPROC *read;
-	FILESEEKPROC *seek;
-} BASS_FILEPROCS;
-
-// BASS_StreamPutFileData options
-#define BASS_FILEDATA_END		0	// end & close the file
-
-// BASS_StreamGetFilePosition modes
-#define BASS_FILEPOS_CURRENT	0
-#define BASS_FILEPOS_DECODE		BASS_FILEPOS_CURRENT
-#define BASS_FILEPOS_DOWNLOAD	1
-#define BASS_FILEPOS_END		2
-#define BASS_FILEPOS_START		3
-#define BASS_FILEPOS_CONNECTED	4
-#define BASS_FILEPOS_BUFFER		5
-#define BASS_FILEPOS_SOCKET		6
-#define BASS_FILEPOS_ASYNCBUF	7
-#define BASS_FILEPOS_SIZE		8
-#define BASS_FILEPOS_BUFFERING	9
-#define BASS_FILEPOS_AVAILABLE	10
-
-typedef void (CALLBACK DOWNLOADPROC)(const void *buffer, DWORD length, void *user);
-/* Internet stream download callback function.
-buffer : Buffer containing the downloaded data... NULL=end of download
-length : Number of bytes in the buffer
-user   : The 'user' parameter value given when calling BASS_StreamCreateURL */
-
-// BASS_ChannelSetSync types
-#define BASS_SYNC_POS			0
-#define BASS_SYNC_END			2
-#define BASS_SYNC_META			4
-#define BASS_SYNC_SLIDE			5
-#define BASS_SYNC_STALL			6
-#define BASS_SYNC_DOWNLOAD		7
-#define BASS_SYNC_FREE			8
-#define BASS_SYNC_SETPOS		11
-#define BASS_SYNC_MUSICPOS		10
-#define BASS_SYNC_MUSICINST		1
-#define BASS_SYNC_MUSICFX		3
-#define BASS_SYNC_OGG_CHANGE	12
-#define BASS_SYNC_DEV_FAIL		14
-#define BASS_SYNC_DEV_FORMAT	15
-#define BASS_SYNC_THREAD		0x20000000	// flag: call sync in other thread
-#define BASS_SYNC_MIXTIME		0x40000000	// flag: sync at mixtime, else at playtime
-#define BASS_SYNC_ONETIME		0x80000000	// flag: sync only once, else continuously
-
-typedef void (CALLBACK SYNCPROC)(HSYNC handle, DWORD channel, DWORD data, void *user);
-/* Sync callback function.
-handle : The sync that has occured
-channel: Channel that the sync occured in
-data   : Additional data associated with the sync's occurance
-user   : The 'user' parameter given when calling BASS_ChannelSetSync */
-
-typedef void (CALLBACK DSPPROC)(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user);
-/* DSP callback function.
-handle : The DSP handle
-channel: Channel that the DSP is being applied to
-buffer : Buffer to apply the DSP to
-length : Number of bytes in the buffer
-user   : The 'user' parameter given when calling BASS_ChannelSetDSP */
-
-typedef BOOL (CALLBACK RECORDPROC)(HRECORD handle, const void *buffer, DWORD length, void *user);
-/* Recording callback function.
-handle : The recording handle
-buffer : Buffer containing the recorded sample data
-length : Number of bytes
-user   : The 'user' parameter value given when calling BASS_RecordStart
-RETURN : TRUE = continue recording, FALSE = stop */
-
-// BASS_ChannelIsActive return values
-#define BASS_ACTIVE_STOPPED			0
-#define BASS_ACTIVE_PLAYING			1
-#define BASS_ACTIVE_STALLED			2
-#define BASS_ACTIVE_PAUSED			3
-#define BASS_ACTIVE_PAUSED_DEVICE	4
-
-// Channel attributes
-#define BASS_ATTRIB_FREQ			1
-#define BASS_ATTRIB_VOL				2
-#define BASS_ATTRIB_PAN				3
-#define BASS_ATTRIB_EAXMIX			4
-#define BASS_ATTRIB_NOBUFFER		5
-#define BASS_ATTRIB_VBR				6
-#define BASS_ATTRIB_CPU				7
-#define BASS_ATTRIB_SRC				8
-#define BASS_ATTRIB_NET_RESUME		9
-#define BASS_ATTRIB_SCANINFO		10
-#define BASS_ATTRIB_NORAMP			11
-#define BASS_ATTRIB_BITRATE			12
-#define BASS_ATTRIB_BUFFER			13
-#define BASS_ATTRIB_GRANULE			14
-#define BASS_ATTRIB_USER			15
-#define BASS_ATTRIB_TAIL			16
-#define BASS_ATTRIB_PUSH_LIMIT		17
-#define BASS_ATTRIB_MUSIC_AMPLIFY	0x100
-#define BASS_ATTRIB_MUSIC_PANSEP	0x101
-#define BASS_ATTRIB_MUSIC_PSCALER	0x102
-#define BASS_ATTRIB_MUSIC_BPM		0x103
-#define BASS_ATTRIB_MUSIC_SPEED		0x104
-#define BASS_ATTRIB_MUSIC_VOL_GLOBAL 0x105
-#define BASS_ATTRIB_MUSIC_ACTIVE	0x106
-#define BASS_ATTRIB_MUSIC_VOL_CHAN	0x200 // + channel #
-#define BASS_ATTRIB_MUSIC_VOL_INST	0x300 // + instrument #
-
-// BASS_ChannelSlideAttribute flags
-#define BASS_SLIDE_LOG				0x1000000
-
-// BASS_ChannelGetData flags
-#define BASS_DATA_AVAILABLE	0			// query how much data is buffered
-#define BASS_DATA_NOREMOVE	0x10000000	// flag: don't remove data from recording buffer
-#define BASS_DATA_FIXED		0x20000000	// flag: return 8.24 fixed-point data
-#define BASS_DATA_FLOAT		0x40000000	// flag: return floating-point sample data
-#define BASS_DATA_FFT256	0x80000000	// 256 sample FFT
-#define BASS_DATA_FFT512	0x80000001	// 512 FFT
-#define BASS_DATA_FFT1024	0x80000002	// 1024 FFT
-#define BASS_DATA_FFT2048	0x80000003	// 2048 FFT
-#define BASS_DATA_FFT4096	0x80000004	// 4096 FFT
-#define BASS_DATA_FFT8192	0x80000005	// 8192 FFT
-#define BASS_DATA_FFT16384	0x80000006	// 16384 FFT
-#define BASS_DATA_FFT32768	0x80000007	// 32768 FFT
-#define BASS_DATA_FFT_INDIVIDUAL 0x10	// FFT flag: FFT for each channel, else all combined
-#define BASS_DATA_FFT_NOWINDOW	0x20	// FFT flag: no Hanning window
-#define BASS_DATA_FFT_REMOVEDC	0x40	// FFT flag: pre-remove DC bias
-#define BASS_DATA_FFT_COMPLEX	0x80	// FFT flag: return complex data
-#define BASS_DATA_FFT_NYQUIST	0x100	// FFT flag: return extra Nyquist value
-
-// BASS_ChannelGetLevelEx flags
-#define BASS_LEVEL_MONO		1	// get mono level
-#define BASS_LEVEL_STEREO	2	// get stereo level
-#define BASS_LEVEL_RMS		4	// get RMS levels
-#define BASS_LEVEL_VOLPAN	8	// apply VOL/PAN attributes to the levels
-#define BASS_LEVEL_NOREMOVE	16	// don't remove data from recording buffer
-
-// BASS_ChannelGetTags types : what's returned
-#define BASS_TAG_ID3		0	// ID3v1 tags : TAG_ID3 structure
-#define BASS_TAG_ID3V2		1	// ID3v2 tags : variable length block
-#define BASS_TAG_OGG		2	// OGG comments : series of null-terminated UTF-8 strings
-#define BASS_TAG_HTTP		3	// HTTP headers : series of null-terminated ASCII strings
-#define BASS_TAG_ICY		4	// ICY headers : series of null-terminated ANSI strings
-#define BASS_TAG_META		5	// ICY metadata : ANSI string
-#define BASS_TAG_APE		6	// APE tags : series of null-terminated UTF-8 strings
-#define BASS_TAG_MP4 		7	// MP4/iTunes metadata : series of null-terminated UTF-8 strings
-#define BASS_TAG_WMA		8	// WMA tags : series of null-terminated UTF-8 strings
-#define BASS_TAG_VENDOR		9	// OGG encoder : UTF-8 string
-#define BASS_TAG_LYRICS3	10	// Lyric3v2 tag : ASCII string
-#define BASS_TAG_CA_CODEC	11	// CoreAudio codec info : TAG_CA_CODEC structure
-#define BASS_TAG_MF			13	// Media Foundation tags : series of null-terminated UTF-8 strings
-#define BASS_TAG_WAVEFORMAT	14	// WAVE format : WAVEFORMATEEX structure
-#define BASS_TAG_AM_NAME	16	// Android Media codec name : ASCII string
-#define BASS_TAG_ID3V2_2	17	// ID3v2 tags (2nd block) : variable length block
-#define BASS_TAG_AM_MIME	18	// Android Media MIME type : ASCII string
-#define BASS_TAG_LOCATION	19	// redirected URL : ASCII string
-#define BASS_TAG_RIFF_INFO	0x100 // RIFF "INFO" tags : series of null-terminated ANSI strings
-#define BASS_TAG_RIFF_BEXT	0x101 // RIFF/BWF "bext" tags : TAG_BEXT structure
-#define BASS_TAG_RIFF_CART	0x102 // RIFF/BWF "cart" tags : TAG_CART structure
-#define BASS_TAG_RIFF_DISP	0x103 // RIFF "DISP" text tag : ANSI string
-#define BASS_TAG_RIFF_CUE	0x104 // RIFF "cue " chunk : TAG_CUE structure
-#define BASS_TAG_RIFF_SMPL	0x105 // RIFF "smpl" chunk : TAG_SMPL structure
-#define BASS_TAG_APE_BINARY	0x1000	// + index #, binary APE tag : TAG_APE_BINARY structure
-#define BASS_TAG_MUSIC_NAME		0x10000	// MOD music name : ANSI string
-#define BASS_TAG_MUSIC_MESSAGE	0x10001	// MOD message : ANSI string
-#define BASS_TAG_MUSIC_ORDERS	0x10002	// MOD order list : BYTE array of pattern numbers
-#define BASS_TAG_MUSIC_AUTH		0x10003	// MOD author : UTF-8 string
-#define BASS_TAG_MUSIC_INST		0x10100	// + instrument #, MOD instrument name : ANSI string
-#define BASS_TAG_MUSIC_CHAN		0x10200	// + channel #, MOD channel name : ANSI string
-#define BASS_TAG_MUSIC_SAMPLE	0x10300	// + sample #, MOD sample name : ANSI string
-
-// ID3v1 tag structure
-typedef struct {
-	char id[3];
-	char title[30];
-	char artist[30];
-	char album[30];
-	char year[4];
-	char comment[30];
-	BYTE genre;
-} TAG_ID3;
-
-// Binary APE tag structure
-typedef struct {
-	const char *key;
-	const void *data;
-	DWORD length;
-} TAG_APE_BINARY;
-
-// BWF "bext" tag structure
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable:4200)
-#endif
-#pragma pack(push,1)
-typedef struct {
-	char Description[256];			// description
-	char Originator[32];			// name of the originator
-	char OriginatorReference[32];	// reference of the originator
-	char OriginationDate[10];		// date of creation (yyyy-mm-dd)
-	char OriginationTime[8];		// time of creation (hh-mm-ss)
-	QWORD TimeReference;			// first sample count since midnight (little-endian)
-	WORD Version;					// BWF version (little-endian)
-	BYTE UMID[64];					// SMPTE UMID
-	BYTE Reserved[190];
-#if defined(__GNUC__) && __GNUC__<3
-	char CodingHistory[0];			// history
-#elif 1 // change to 0 if compiler fails the following line
-	char CodingHistory[];			// history
-#else
-	char CodingHistory[1];			// history
-#endif
-} TAG_BEXT;
-#pragma pack(pop)
-
-// BWF "cart" tag structures
-typedef struct
-{
-	DWORD dwUsage;					// FOURCC timer usage ID
-	DWORD dwValue;					// timer value in samples from head
-} TAG_CART_TIMER;
-
-typedef struct
-{
-	char Version[4];				// version of the data structure
-	char Title[64];					// title of cart audio sequence
-	char Artist[64];				// artist or creator name
-	char CutID[64];					// cut number identification
-	char ClientID[64];				// client identification
-	char Category[64];				// category ID, PSA, NEWS, etc
-	char Classification[64];		// classification or auxiliary key
-	char OutCue[64];				// out cue text
-	char StartDate[10];				// yyyy-mm-dd
-	char StartTime[8];				// hh:mm:ss
-	char EndDate[10];				// yyyy-mm-dd
-	char EndTime[8];				// hh:mm:ss
-	char ProducerAppID[64];			// name of vendor or application
-	char ProducerAppVersion[64];	// version of producer application
-	char UserDef[64];				// user defined text
-	DWORD dwLevelReference;			// sample value for 0 dB reference
-	TAG_CART_TIMER PostTimer[8];	// 8 time markers after head
-	char Reserved[276];
-	char URL[1024];					// uniform resource locator
-#if defined(__GNUC__) && __GNUC__<3
-	char TagText[0];				// free form text for scripts or tags
-#elif 1 // change to 0 if compiler fails the following line
-	char TagText[];					// free form text for scripts or tags
-#else
-	char TagText[1];				// free form text for scripts or tags
-#endif
-} TAG_CART;
-
-// RIFF "cue " tag structures
-typedef struct
-{
-	DWORD dwName;
-	DWORD dwPosition;
-	DWORD fccChunk;
-	DWORD dwChunkStart;
-	DWORD dwBlockStart;
-	DWORD dwSampleOffset;
-} TAG_CUE_POINT;
-
-typedef struct
-{
-	DWORD dwCuePoints;
-#if defined(__GNUC__) && __GNUC__<3
-	TAG_CUE_POINT CuePoints[0];
-#elif 1 // change to 0 if compiler fails the following line
-	TAG_CUE_POINT CuePoints[];
-#else
-	TAG_CUE_POINT CuePoints[1];
-#endif
-} TAG_CUE;
-
-// RIFF "smpl" tag structures
-typedef struct
-{
-	DWORD dwIdentifier;
-	DWORD dwType;
-	DWORD dwStart;
-	DWORD dwEnd;
-	DWORD dwFraction;
-	DWORD dwPlayCount;
-} TAG_SMPL_LOOP;
-
-typedef struct
-{
-	DWORD dwManufacturer;
-	DWORD dwProduct;
-	DWORD dwSamplePeriod;
-	DWORD dwMIDIUnityNote;
-	DWORD dwMIDIPitchFraction;
-	DWORD dwSMPTEFormat;
-	DWORD dwSMPTEOffset;
-	DWORD cSampleLoops;
-	DWORD cbSamplerData;
-#if defined(__GNUC__) && __GNUC__<3
-	TAG_SMPL_LOOP SampleLoops[0];
-#elif 1 // change to 0 if compiler fails the following line
-	TAG_SMPL_LOOP SampleLoops[];
-#else
-	TAG_SMPL_LOOP SampleLoops[1];
-#endif
-} TAG_SMPL;
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
-// CoreAudio codec info structure
-typedef struct {
-	DWORD ftype;					// file format
-	DWORD atype;					// audio format
-	const char *name;				// description
-} TAG_CA_CODEC;
-
-#ifndef _WAVEFORMATEX_
-#define _WAVEFORMATEX_
-#pragma pack(push,1)
-typedef struct tWAVEFORMATEX
-{
-	WORD wFormatTag;
-	WORD nChannels;
-	DWORD nSamplesPerSec;
-	DWORD nAvgBytesPerSec;
-	WORD nBlockAlign;
-	WORD wBitsPerSample;
-	WORD cbSize;
-} WAVEFORMATEX, *PWAVEFORMATEX, *LPWAVEFORMATEX;
-typedef const WAVEFORMATEX *LPCWAVEFORMATEX;
-#pragma pack(pop)
-#endif
-
-// BASS_ChannelGetLength/GetPosition/SetPosition modes
-#define BASS_POS_BYTE			0		// byte position
-#define BASS_POS_MUSIC_ORDER	1		// order.row position, MAKELONG(order,row)
-#define BASS_POS_OGG			3		// OGG bitstream number
-#define BASS_POS_END			0x10	// trimmed end position
-#define BASS_POS_LOOP			0x11	// loop start positiom
-#define BASS_POS_FLUSH			0x1000000 // flag: flush decoder/FX buffers
-#define BASS_POS_RESET			0x2000000 // flag: reset user file buffers
-#define BASS_POS_RELATIVE		0x4000000 // flag: seek relative to the current position
-#define BASS_POS_INEXACT		0x8000000 // flag: allow seeking to inexact position
-#define BASS_POS_DECODE			0x10000000 // flag: get the decoding (not playing) position
-#define BASS_POS_DECODETO		0x20000000 // flag: decode to the position instead of seeking
-#define BASS_POS_SCAN			0x40000000 // flag: scan to the position
-
-// BASS_ChannelSetDevice/GetDevice option
-#define BASS_NODEVICE		0x20000
-
-// BASS_RecordSetInput flags
-#define BASS_INPUT_OFF		0x10000
-#define BASS_INPUT_ON		0x20000
-
-#define BASS_INPUT_TYPE_MASK		0xff000000
-#define BASS_INPUT_TYPE_UNDEF		0x00000000
-#define BASS_INPUT_TYPE_DIGITAL		0x01000000
-#define BASS_INPUT_TYPE_LINE		0x02000000
-#define BASS_INPUT_TYPE_MIC			0x03000000
-#define BASS_INPUT_TYPE_SYNTH		0x04000000
-#define BASS_INPUT_TYPE_CD			0x05000000
-#define BASS_INPUT_TYPE_PHONE		0x06000000
-#define BASS_INPUT_TYPE_SPEAKER		0x07000000
-#define BASS_INPUT_TYPE_WAVE		0x08000000
-#define BASS_INPUT_TYPE_AUX			0x09000000
-#define BASS_INPUT_TYPE_ANALOG		0x0a000000
-
-// BASS_ChannelSetFX effect types
-#define BASS_FX_DX8_CHORUS			0
-#define BASS_FX_DX8_COMPRESSOR		1
-#define BASS_FX_DX8_DISTORTION		2
-#define BASS_FX_DX8_ECHO			3
-#define BASS_FX_DX8_FLANGER			4
-#define BASS_FX_DX8_GARGLE			5
-#define BASS_FX_DX8_I3DL2REVERB		6
-#define BASS_FX_DX8_PARAMEQ			7
-#define BASS_FX_DX8_REVERB			8
-#define BASS_FX_VOLUME				9
-
-typedef struct {
-	float       fWetDryMix;
-	float       fDepth;
-	float       fFeedback;
-	float       fFrequency;
-	DWORD       lWaveform;	// 0=triangle, 1=sine
-	float       fDelay;
-	DWORD       lPhase;		// BASS_DX8_PHASE_xxx
-} BASS_DX8_CHORUS;
-
-typedef struct {
-	float   fGain;
-	float   fAttack;
-	float   fRelease;
-	float   fThreshold;
-	float   fRatio;
-	float   fPredelay;
-} BASS_DX8_COMPRESSOR;
-
-typedef struct {
-	float   fGain;
-	float   fEdge;
-	float   fPostEQCenterFrequency;
-	float   fPostEQBandwidth;
-	float   fPreLowpassCutoff;
-} BASS_DX8_DISTORTION;
-
-typedef struct {
-	float   fWetDryMix;
-	float   fFeedback;
-	float   fLeftDelay;
-	float   fRightDelay;
-	BOOL    lPanDelay;
-} BASS_DX8_ECHO;
-
-typedef struct {
-	float       fWetDryMix;
-	float       fDepth;
-	float       fFeedback;
-	float       fFrequency;
-	DWORD       lWaveform;	// 0=triangle, 1=sine
-	float       fDelay;
-	DWORD       lPhase;		// BASS_DX8_PHASE_xxx
-} BASS_DX8_FLANGER;
-
-typedef struct {
-	DWORD       dwRateHz;               // Rate of modulation in hz
-	DWORD       dwWaveShape;            // 0=triangle, 1=square
-} BASS_DX8_GARGLE;
-
-typedef struct {
-	int     lRoom;                  // [-10000, 0]      default: -1000 mB
-	int     lRoomHF;                // [-10000, 0]      default: 0 mB
-	float   flRoomRolloffFactor;    // [0.0, 10.0]      default: 0.0
-	float   flDecayTime;            // [0.1, 20.0]      default: 1.49s
-	float   flDecayHFRatio;         // [0.1, 2.0]       default: 0.83
-	int     lReflections;           // [-10000, 1000]   default: -2602 mB
-	float   flReflectionsDelay;     // [0.0, 0.3]       default: 0.007 s
-	int     lReverb;                // [-10000, 2000]   default: 200 mB
-	float   flReverbDelay;          // [0.0, 0.1]       default: 0.011 s
-	float   flDiffusion;            // [0.0, 100.0]     default: 100.0 %
-	float   flDensity;              // [0.0, 100.0]     default: 100.0 %
-	float   flHFReference;          // [20.0, 20000.0]  default: 5000.0 Hz
-} BASS_DX8_I3DL2REVERB;
-
-typedef struct {
-	float   fCenter;
-	float   fBandwidth;
-	float   fGain;
-} BASS_DX8_PARAMEQ;
-
-typedef struct {
-	float   fInGain;                // [-96.0,0.0]            default: 0.0 dB
-	float   fReverbMix;             // [-96.0,0.0]            default: 0.0 db
-	float   fReverbTime;            // [0.001,3000.0]         default: 1000.0 ms
-	float   fHighFreqRTRatio;       // [0.001,0.999]          default: 0.001
-} BASS_DX8_REVERB;
-
-#define BASS_DX8_PHASE_NEG_180        0
-#define BASS_DX8_PHASE_NEG_90         1
-#define BASS_DX8_PHASE_ZERO           2
-#define BASS_DX8_PHASE_90             3
-#define BASS_DX8_PHASE_180            4
-
-typedef struct {
-	float fTarget;
-	float fCurrent;
-	float fTime;
-	DWORD lCurve;
-} BASS_FX_VOLUME_PARAM;
-
-typedef void (CALLBACK IOSNOTIFYPROC)(DWORD status);
-/* iOS notification callback function.
-status : The notification (BASS_IOSNOTIFY_xxx) */
-
-#define BASS_IOSNOTIFY_INTERRUPT		1	// interruption started
-#define BASS_IOSNOTIFY_INTERRUPT_END	2	// interruption ended
-
-BOOL BASSDEF(BASS_SetConfig)(DWORD option, DWORD value);
-DWORD BASSDEF(BASS_GetConfig)(DWORD option);
-BOOL BASSDEF(BASS_SetConfigPtr)(DWORD option, const void *value);
-const void *BASSDEF(BASS_GetConfigPtr)(DWORD option);
-DWORD BASSDEF(BASS_GetVersion)(void);
-int BASSDEF(BASS_ErrorGetCode)(void);
-
-BOOL BASSDEF(BASS_GetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info);
-#if defined(_WIN32) && !defined(_WIN32_WCE) && !(defined(WINAPI_FAMILY) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
-BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, HWND win, const void *dsguid);
-#else
-BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, void *win, const void *dsguid);
-#endif
-BOOL BASSDEF(BASS_Free)(void);
-BOOL BASSDEF(BASS_SetDevice)(DWORD device);
-DWORD BASSDEF(BASS_GetDevice)(void);
-BOOL BASSDEF(BASS_GetInfo)(BASS_INFO *info);
-BOOL BASSDEF(BASS_Start)(void);
-BOOL BASSDEF(BASS_Stop)(void);
-BOOL BASSDEF(BASS_Pause)(void);
-DWORD BASSDEF(BASS_IsStarted)(void);
-BOOL BASSDEF(BASS_Update)(DWORD length);
-float BASSDEF(BASS_GetCPU)(void);
-BOOL BASSDEF(BASS_SetVolume)(float volume);
-float BASSDEF(BASS_GetVolume)(void);
-#if defined(_WIN32) && !defined(_WIN32_WCE) && !(defined(WINAPI_FAMILY) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
-void *BASSDEF(BASS_GetDSoundObject)(DWORD object);
-#endif
-
-BOOL BASSDEF(BASS_Set3DFactors)(float distf, float rollf, float doppf);
-BOOL BASSDEF(BASS_Get3DFactors)(float *distf, float *rollf, float *doppf);
-BOOL BASSDEF(BASS_Set3DPosition)(const BASS_3DVECTOR *pos, const BASS_3DVECTOR *vel, const BASS_3DVECTOR *front, const BASS_3DVECTOR *top);
-BOOL BASSDEF(BASS_Get3DPosition)(BASS_3DVECTOR *pos, BASS_3DVECTOR *vel, BASS_3DVECTOR *front, BASS_3DVECTOR *top);
-void BASSDEF(BASS_Apply3D)(void);
-
-HPLUGIN BASSDEF(BASS_PluginLoad)(const char *file, DWORD flags);
-BOOL BASSDEF(BASS_PluginFree)(HPLUGIN handle);
-BOOL BASSDEF(BASS_PluginEnable)(HPLUGIN handle, BOOL enable);
-const BASS_PLUGININFO *BASSDEF(BASS_PluginGetInfo)(HPLUGIN handle);
-
-HSAMPLE BASSDEF(BASS_SampleLoad)(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD max, DWORD flags);
-HSAMPLE BASSDEF(BASS_SampleCreate)(DWORD length, DWORD freq, DWORD chans, DWORD max, DWORD flags);
-BOOL BASSDEF(BASS_SampleFree)(HSAMPLE handle);
-BOOL BASSDEF(BASS_SampleSetData)(HSAMPLE handle, const void *buffer);
-BOOL BASSDEF(BASS_SampleGetData)(HSAMPLE handle, void *buffer);
-BOOL BASSDEF(BASS_SampleGetInfo)(HSAMPLE handle, BASS_SAMPLE *info);
-BOOL BASSDEF(BASS_SampleSetInfo)(HSAMPLE handle, const BASS_SAMPLE *info);
-DWORD BASSDEF(BASS_SampleGetChannel)(HSAMPLE handle, DWORD flags);
-DWORD BASSDEF(BASS_SampleGetChannels)(HSAMPLE handle, HCHANNEL *channels);
-BOOL BASSDEF(BASS_SampleStop)(HSAMPLE handle);
-
-HSTREAM BASSDEF(BASS_StreamCreate)(DWORD freq, DWORD chans, DWORD flags, STREAMPROC *proc, void *user);
-HSTREAM BASSDEF(BASS_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags);
-HSTREAM BASSDEF(BASS_StreamCreateURL)(const char *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user);
-HSTREAM BASSDEF(BASS_StreamCreateFileUser)(DWORD system, DWORD flags, const BASS_FILEPROCS *proc, void *user);
-BOOL BASSDEF(BASS_StreamFree)(HSTREAM handle);
-QWORD BASSDEF(BASS_StreamGetFilePosition)(HSTREAM handle, DWORD mode);
-DWORD BASSDEF(BASS_StreamPutData)(HSTREAM handle, const void *buffer, DWORD length);
-DWORD BASSDEF(BASS_StreamPutFileData)(HSTREAM handle, const void *buffer, DWORD length);
-
-HMUSIC BASSDEF(BASS_MusicLoad)(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD flags, DWORD freq);
-BOOL BASSDEF(BASS_MusicFree)(HMUSIC handle);
-
-BOOL BASSDEF(BASS_RecordGetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info);
-BOOL BASSDEF(BASS_RecordInit)(int device);
-BOOL BASSDEF(BASS_RecordFree)(void);
-BOOL BASSDEF(BASS_RecordSetDevice)(DWORD device);
-DWORD BASSDEF(BASS_RecordGetDevice)(void);
-BOOL BASSDEF(BASS_RecordGetInfo)(BASS_RECORDINFO *info);
-const char *BASSDEF(BASS_RecordGetInputName)(int input);
-BOOL BASSDEF(BASS_RecordSetInput)(int input, DWORD flags, float volume);
-DWORD BASSDEF(BASS_RecordGetInput)(int input, float *volume);
-HRECORD BASSDEF(BASS_RecordStart)(DWORD freq, DWORD chans, DWORD flags, RECORDPROC *proc, void *user);
-
-double BASSDEF(BASS_ChannelBytes2Seconds)(DWORD handle, QWORD pos);
-QWORD BASSDEF(BASS_ChannelSeconds2Bytes)(DWORD handle, double pos);
-DWORD BASSDEF(BASS_ChannelGetDevice)(DWORD handle);
-BOOL BASSDEF(BASS_ChannelSetDevice)(DWORD handle, DWORD device);
-DWORD BASSDEF(BASS_ChannelIsActive)(DWORD handle);
-BOOL BASSDEF(BASS_ChannelGetInfo)(DWORD handle, BASS_CHANNELINFO *info);
-const char *BASSDEF(BASS_ChannelGetTags)(DWORD handle, DWORD tags);
-DWORD BASSDEF(BASS_ChannelFlags)(DWORD handle, DWORD flags, DWORD mask);
-BOOL BASSDEF(BASS_ChannelLock)(DWORD handle, BOOL lock);
-BOOL BASSDEF(BASS_ChannelFree)(DWORD handle);
-BOOL BASSDEF(BASS_ChannelPlay)(DWORD handle, BOOL restart);
-BOOL BASSDEF(BASS_ChannelStop)(DWORD handle);
-BOOL BASSDEF(BASS_ChannelPause)(DWORD handle);
-BOOL BASSDEF(BASS_ChannelUpdate)(DWORD handle, DWORD length);
-BOOL BASSDEF(BASS_ChannelSetAttribute)(DWORD handle, DWORD attrib, float value);
-BOOL BASSDEF(BASS_ChannelGetAttribute)(DWORD handle, DWORD attrib, float *value);
-BOOL BASSDEF(BASS_ChannelSlideAttribute)(DWORD handle, DWORD attrib, float value, DWORD time);
-BOOL BASSDEF(BASS_ChannelIsSliding)(DWORD handle, DWORD attrib);
-BOOL BASSDEF(BASS_ChannelSetAttributeEx)(DWORD handle, DWORD attrib, void *value, DWORD size);
-DWORD BASSDEF(BASS_ChannelGetAttributeEx)(DWORD handle, DWORD attrib, void *value, DWORD size);
-BOOL BASSDEF(BASS_ChannelSet3DAttributes)(DWORD handle, int mode, float min, float max, int iangle, int oangle, float outvol);
-BOOL BASSDEF(BASS_ChannelGet3DAttributes)(DWORD handle, DWORD *mode, float *min, float *max, DWORD *iangle, DWORD *oangle, float *outvol);
-BOOL BASSDEF(BASS_ChannelSet3DPosition)(DWORD handle, const BASS_3DVECTOR *pos, const BASS_3DVECTOR *orient, const BASS_3DVECTOR *vel);
-BOOL BASSDEF(BASS_ChannelGet3DPosition)(DWORD handle, BASS_3DVECTOR *pos, BASS_3DVECTOR *orient, BASS_3DVECTOR *vel);
-QWORD BASSDEF(BASS_ChannelGetLength)(DWORD handle, DWORD mode);
-BOOL BASSDEF(BASS_ChannelSetPosition)(DWORD handle, QWORD pos, DWORD mode);
-QWORD BASSDEF(BASS_ChannelGetPosition)(DWORD handle, DWORD mode);
-DWORD BASSDEF(BASS_ChannelGetLevel)(DWORD handle);
-BOOL BASSDEF(BASS_ChannelGetLevelEx)(DWORD handle, float *levels, float length, DWORD flags);
-DWORD BASSDEF(BASS_ChannelGetData)(DWORD handle, void *buffer, DWORD length);
-HSYNC BASSDEF(BASS_ChannelSetSync)(DWORD handle, DWORD type, QWORD param, SYNCPROC *proc, void *user);
-BOOL BASSDEF(BASS_ChannelRemoveSync)(DWORD handle, HSYNC sync);
-BOOL BASSDEF(BASS_ChannelSetLink)(DWORD handle, DWORD chan);
-BOOL BASSDEF(BASS_ChannelRemoveLink)(DWORD handle, DWORD chan);
-HDSP BASSDEF(BASS_ChannelSetDSP)(DWORD handle, DSPPROC *proc, void *user, int priority);
-BOOL BASSDEF(BASS_ChannelRemoveDSP)(DWORD handle, HDSP dsp);
-HFX BASSDEF(BASS_ChannelSetFX)(DWORD handle, DWORD type, int priority);
-BOOL BASSDEF(BASS_ChannelRemoveFX)(DWORD handle, HFX fx);
-
-BOOL BASSDEF(BASS_FXSetParameters)(HFX handle, const void *params);
-BOOL BASSDEF(BASS_FXGetParameters)(HFX handle, void *params);
-BOOL BASSDEF(BASS_FXSetPriority)(HFX handle, int priority);
-BOOL BASSDEF(BASS_FXReset)(DWORD handle);
-
-#ifdef __cplusplus
-}
-
-#if defined(_WIN32) && !defined(NOBASSOVERLOADS)
-static inline HPLUGIN BASS_PluginLoad(const WCHAR *file, DWORD flags)
-{
-	return BASS_PluginLoad((const char*)file, flags | BASS_UNICODE);
-}
-
-static inline HMUSIC BASS_MusicLoad(BOOL mem, const WCHAR *file, QWORD offset, DWORD length, DWORD flags, DWORD freq)
-{
-	return BASS_MusicLoad(mem, (const void*)file, offset, length, flags | BASS_UNICODE, freq);
-}
-
-static inline HSAMPLE BASS_SampleLoad(BOOL mem, const WCHAR *file, QWORD offset, DWORD length, DWORD max, DWORD flags)
-{
-	return BASS_SampleLoad(mem, (const void*)file, offset, length, max, flags | BASS_UNICODE);
-}
-
-static inline HSTREAM BASS_StreamCreateFile(BOOL mem, const WCHAR *file, QWORD offset, QWORD length, DWORD flags)
-{
-	return BASS_StreamCreateFile(mem, (const void*)file, offset, length, flags | BASS_UNICODE);
-}
-
-static inline HSTREAM BASS_StreamCreateURL(const WCHAR *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user)
-{
-	return BASS_StreamCreateURL((const char*)url, offset, flags | BASS_UNICODE, proc, user);
-}
-
-static inline BOOL BASS_SetConfigPtr(DWORD option, const WCHAR *value)
-{
-	return BASS_SetConfigPtr(option | BASS_UNICODE, (const void*)value);
-}
-#endif
-#endif
-
-#ifdef __OBJC__
-#undef BOOL
-#endif
-
-#endif

+ 0 - 2272
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bass.txt

@@ -1,2272 +0,0 @@
-BASS 2.4
-Copyright (c) 1999-2021 Un4seen Developments Ltd. All rights reserved.
-
-Files that you should have found in the BASS package
-====================================================
-Win32 version
--------------
-BASS.TXT        This file
-BASS.DLL        BASS module
-BASS.CHM        BASS documentation
-X64\
-  BASS.DLL        64-bit BASS module
-C\              C/C++ API and examples...
-  BASS.H          BASS C/C++ header file
-  BASS.LIB        BASS import library
-  BASS.SLN        Visual Studio solution for examples
-  MAKEFILE        Makefile for examples
-  MAKEFILE.IN     Makefile helper macros
-  X64\
-    BASS.LIB        64-bit BASS import library
-  3DTEST\         3D example
-    ...
-  BASSTEST\       Simple playback example
-    ...
-  CONTEST\        Console example
-    ...
-  CUSTLOOP\       Custom looping example
-    ...
-  DEVLIST\        Device list example
-    ...
-  DSPTEST\        DSP example
-    ...
-  FXTEST\         Effects example
-    ...
-  LIVEFX\         Full-duplex example
-    ...
-  LIVESPEC\       Live version of spectrum analyser example
-    ...
-  MODTEST\        MOD music example
-    ...
-  MULTI\          Multiple device example
-    ...
-  NETRADIO\       Internet streaming example
-    ...
-  PLUGINS\        Plugins example
-    ...
-  RECTEST\        Recording example
-    ...
-  SPEAKERS\       Multi-speaker example
-    ...
-  SPECTRUM\       Spectrum analyser example
-    ...
-  SYNTH\          Low latency custom streaming example
-    ...
-  WRITEWAV\       WAVE writer example
-    ...
-  BIN\            Precompiled examples
-    3DTEST.EXE
-    BASSTEST.EXE
-    CONTEST.EXE
-    CUSTLOOP.EXE
-    DEVLIST.EXE
-    DSPTEST.EXE
-    FXTEST.EXE
-    LIVEFX.EXE
-    LIVESPEC.EXE
-    MODTEST.EXE
-    MULTI.EXE
-    NETRADIO.EXE
-    RECTEST.EXE
-    SPEAKERS.EXE
-    SPECTRUM.EXE
-    SYNTH.EXE
-    WRITEWAV.EXE
-DELPHI\         Delphi API and examples...
-  BASS.PAS        BASS Delphi unit
-  3DTEST\         3D example
-    ...
-  BASSTEST\       Simple playback example
-    ...
-  CONTEST\        Console example
-    ...
-  CUSTLOOP\       Custom looping example
-    ...
-  DSPTEST\        DSP example
-    ...
-  FXTEST\         Effects example
-    ...
-  LIVEFX\         Full-duplex example
-    ...
-  LIVESPEC\       Live version of spectrum analyser example
-    ...
-  MULTI\          Multiple device example
-    ...
-  NETRADIO\       Internet streaming example
-    ...
-  PLUGINS\        Plugins example
-    ...
-  RECTEST\        Recording example
-    ...
-  SAMPLEVIS\      Visualisation example
-    ...
-  SPEAKERS\       Multi-speaker example
-    ...
-  SPECTRUM\       Spectrum analyser example
-    ...
-  STREAMTEST\     User stream example
-    ...
-  WRITEWAV\       WAVE writer example
-    ...
-VB\             Visual Basic API and examples...
-  BASS.BAS        BASS Visual Basic module
-  3DTEST\         3D example
-    ...
-  BASSTEST\       Simple playback example
-    ...
-  CUSTLOOP\       Custom looping example
-    ...
-  DSPTEST\        DSP example
-    ...
-  FXTEST\         Effects example
-    ...
-  LIVEFX\         Full-duplex example
-    ...
-  LIVESPEC\       Live version of spectrum analyser example
-    ...
-  MULTI\          Multiple device example
-    ...
-  NETRADIO\       Internet streaming example
-    ...
-  PLUGINS\        Plugins example
-    ...
-  RECTEST\        Recording example
-    ...
-  SPEAKERS\       Multi-speaker example
-    ...
-  SPECTRUM\       Spectrum analyser example
-    ...
-  SYNTH\          Low latency custom streaming example
-    ...
-  WRITEWAV\       WAVE writer example
-    ...
-  MEMORY\         Playing from memory example by Jobnik
-    ...
-
-NOTE: You may need to "Unblock" the BASS.CHM file in its "Properties" to view
-      it on Windows 7. The documentation can also be viewed online at the BASS
-      website.
-
-NOTE: The Delphi and VB examples may not always be up to date with the C
-      examples, so the latter should be preferred as references if possible.
-
-NOTE: To run the example EXEs, first you will need to copy BASS.DLL into the
-      same directory as them.
-
-macOS version
--------------
-BASS.TXT        This file
-LIBBASS.DYLIB   BASS module
-BASS.CHM        BASS documentation
-CHMOX.APP       CHM file viewer
-BASS.H          BASS C/C++ header file
-BASS.XCODEPROJ  Xcode project for examples
-MAKEFILE        Makefile for specific architectures
-CONTEST\        Console example
-  ...
-DEVLIST\        Device list example
-  ...
-DSPTEST\        DSP example
-  ...
-FXTEST\         Effects example
-  ...
-LIVESPEC\       Live version of spectrum analyser example
-  ...
-MULTI\          Multiple device example
-  ...
-NETRADIO\       Internet streaming example
-  ...
-PLUGINS\        Plugins example
-  ...
-RECTEST\        Recording example
-  ...
-SPEAKERS\       Multi-speaker example
-  ...
-SPECTRUM\       Spectrum analyser example
-  ...
-SYNTH\          Low latency custom streaming example
-  ...
-WRITEWAV\       WAVE writer example
-  ...
-
-NOTE: To view the documentation, you will need a CHM viewer, such as the
-      included CHMOX. The documentation can also be viewed online at the BASS
-      website.
-
-Linux version
--------------
-BASS.TXT        This file
-LIBBASS.SO      BASS module
-BASS.CHM        BASS documentation
-BASS.H          BASS C/C++ header file
-MAKEFILE        Makefile for examples
-MAKEFILE.IN     Makefile helper macros
-X64\
-  LIBBASS.SO      64-bit BASS module
-PASCAL\
-  BASS.PAS        BASS Delphi/Pascal unit
-3DTEST\         3D example
-  ...
-BASSTEST\       Simple playback example
-  ...
-CONTEST\        Console example
-  ...
-CUSTLOOP\       Custom looping example
-  ...
-DEVLIST\        Device list example
-  ...
-DSPTEST\        DSP example
-  ...
-FXTEST\         Effects example
-  ...
-LIVESPEC\       Live version of spectrum analyser example
-  ...
-MODTEST\        MOD music example
-  ...
-MULTI\          Multiple device example
-  ...
-NETRADIO\       Internet streaming example
-  ...
-PLUGINS\        Plugins example
-  ...
-RECTEST\        Recording example
-  ...
-SPEAKERS\       Multi-speaker example
-  ...
-SPECTRUM\       Spectrum analyser example
-  ...
-SYNTH\          Low latency custom streaming example
-  ...
-WRITEWAV\       WAVE writer example
-  ...
-
-NOTE: To view the documentation, you will need a CHM viewer. The documentation
-      can also be viewed online at the BASS website.
-
-Android version
----------------
-BASS.TXT        This file
-BASS.CHM        BASS documentation
-LIBS\           BASS modules
-  ...
-C\              C/C++ API...
-  BASS.H          BASS C/C++ header file
-JAVA\COM\UN4SEEN\BASS\
-  BASS.JAVA       BASS Java class
-EXAMPLES\       Java examples
-  BUILD.GRADLE    Android Studio build script for examples
-  SETTINGS.GRADLE
-  PROGUARD-BASS.PRO
-  DSPTEST\        DSP example
-    ...
-  FXTEST\         Effects example
-    ...
-  LIVESPEC\       Live version of spectrum analyser example
-    ...
-  NETRADIO\       Internet streaming example
-    ...
-  PLUGINS\        Plugins example
-    ...
-  RECTEST\        Recording example
-    ...
-  SPECTRUM\       Spectrum analyser example
-    ...
-
-NOTE: To view the documentation, you will need a CHM viewer. The documentation
-      can also be viewed online at the BASS website.
-
-iOS version
------------
-BASS.TXT        This file
-BASS.CHM        BASS documentation
-BASS.H          BASS C/C++ header file
-BASS.XCFRAMEWORK  BASS framework
-
-NOTE: To view the documentation, you will need a CHM viewer. The documentation
-      can also be viewed online at the BASS website.
-
-
-What's the point?
-=================
-BASS is an audio library for use in software on several platforms. Its purpose
-is to provide developers with powerful and efficient sample, stream, MOD music,
-and recording functions. All in a compact DLL that won't bloat your software.
-
-See the documentation for descriptions of all the BASS functions. Also check
-the included example source-codes for some examples of how to use BASS in your
-own programs.
-
-
-Requirements
-============
-Win32 version
--------------
-BASS requires WASAPI or DirectSound for playback and recording, but decoding
-and silent playback on the "No sound" device is still possible without them.
-DirectSound has been included with all Windows versions since Windows 98. On
-Windows Vista and above, the default is to use WASAPI instead of DirectSound.
-32-bit and 64-bit Windows are supported.
-
-macOS version
--------------
-macOS 10.5 or above is required. BASS uses CoreAudio for playback and recording,
-so there are no special library/driver requirements. x86_64 / arm64 / i386
-architectures are supported in a single universal library.
-
-Linux version
--------------
-BASS requires ALSA for playback and recording, but decoding and silent playback
-on the "No sound" device is still possible without it. 32-bit (i386) and 64-bit
-(x86-64) architectures are supported. ARM support is also available as a
-separate download from the website.
-
-Android version
----------------
-Android 2.3 or above is required. BASS can use AAudio, OpenSL ES, or AudioTrack
-for playback (OpenSL ES is used for recording). AAudio is the default on Android
-8.1 and above, and OpenSL ES is on older Android versions. The armeabi-v7a /
-arm64-v8a / x86 / x86_64 architectures are supported.
-
-iOS version
------------
-iOS 6 or above is required. BASS uses CoreAudio for playback and recording,
-so there are no special library/driver requirements. armv7 / armv7s / arm64
-"device" builds and i386 / x86_64 / arm64 "simulator" builds are supported
-in a single universal framework.
-
-
-Main Features
-=============
-* Samples
-  supports WAV/AIFF/MP3/MP2/MP1/OGG and custom generated samples
-
-* Sample streams
-  stream any sample data in 8/16/32 bit, with both "push" and "pull" systems
-
-* File streams
-  MP3/MP2/MP1/OGG/WAV/AIFF file streaming
-
-* Internet file streaming
-  stream files from the internet, including Shout/Icecast
-
-* User file streaming
-  stream files from anywhere using any delivery method
-
-* OS codecs
-  ACM, Media Foundation and CoreAudio codec support for additional audio formats
-
-* Multi-channel streaming
-  support for more than plain stereo, including multi-channel OGG/WAV/AIFF files
-
-* MOD music
-  uses the same engine as XMPlay = best accuracy, speed, and quality
-
-* MO3 music
-  MP3/OGG compressed MOD music
-
-* Add-on system
-  support for more formats is available via add-ons (aka plugins)
-
-* Multiple outputs
-  simultaneously use multiple soundcards, and move channels between them
-
-* Recording
-  flexible recording system, with support for multiple devices
-
-* Decode without playback
-  streams and MOD musics can be outputted in any way you want
-
-* Speaker assignment
-  assign streams and MOD musics to specific speakers
-
-* High precision synchronization
-  synchronize events in your software to the streams and MOD musics
-
-* Effects
-  chorus/compressor/distortion/echo/flanger/gargle/parameq/reverb
-
-* User-defined DSP functions
-  custom effects may be applied to individual streams or the final output mix
-
-* 32 bit floating-point decoding and processing
-  floating-point stream/music decoding, DSP/FX, and recording
-
-* 3D sound
-  play samples/streams/musics in any 3D position
-
-
-Using BASS
-==========
-There is no guarantee that all future BASS versions will be compatible
-with all previous versions, so your program should use BASS_GetVersion
-to check the version that is loaded. This also means that you should
-put the BASS module in the same directory as your executable (not just
-somewhere in the path), to avoid the possibility of a wrong version being
-loaded.
-
-If you are updating your software from a previous BASS version, then
-you should check the "History" section (below), to see if any of the
-functions that you are using have been affected by a change.
-
-Win32 version
--------------
-C/C++, Delphi, and Visual Basic APIs and example projects are provided. To
-use BASS with another language you will first have to convert the header
-file. Or, as a last resort, you could use LoadLibrary and GetProcAddress.
-
-The downside is that you have to manually import each function that you
-use, with the GetProcAddress function. But it has been made a lot simpler
-to import BASS this way by the use of the BASSDEF #define. Here's a small
-example:
-
-#define BASSDEF(f) (WINAPI *f) // define the functions as pointers
-#include "bass.h"
-...
-HINSTANCE bass=LoadLibrary("BASS.DLL"); // load BASS
-BASS_Init=GetProcAddress(bass,"BASS_Init"); // get BASS_Init
-BASS_Init(-1,44100,0,hWnd,NULL); // call BASS_Init
-
-To use BASS with Borland C++ Builder, you will first have to create a
-Borland C++ Builder import library for it. This is done by using the
-IMPLIB tool that comes with Borland C++ Builder. Simply execute this:
-
-	IMPLIB BASSBCB.LIB BASS.DLL
-
-... and then use BASSBCB.LIB in your projects to import BASS.
-
-To use BASS with LCC-Win32, you will first have to create a compatible
-import library for it. This is done by using the PEDUMP and BUILDLIB
-tools that come with LCC-Win32. Run these 2 commands:
-
-	PEDUMP /EXP BASS.LIB > BASSLCC.EXP
-	BUILDLIB BASSLCC.EXP BASSLCC.LIB
-
-... and then use BASSLCC.LIB in your projects to import BASS.
-
-For the BASS functions that return strings (char*), VB users should use
-the VBStrFromAnsiPtr function to convert the returned pointer into a VB
-string.
-
-macOS version
--------------
-See the example Xcode project.
-
-NOTE: The LIBBASS.DYLIB file must be put in the same directory as the
-      executable, it can't just be somewhere in the path.
-
-LIBBASS.DYLIB is a universal binary with support for the x86_64 / arm64 / i386
-architectures. If not all of those architectures are needed, the included
-makefile can be used to extract the wanted one(s). Type "make x86_64" or
-"make arm64" or "make i386" to extract a particular architecture. "make 64bit"
-can be used to extract the x86_64 and arm64 architectures (exclude i386), and
-"make intel" to extract the x86_64 and i386 architectures (exclude arm64). Any
-BASS add-ons placed in the same directory will also be processed.
-
-Linux version
--------------
-The LIBBASS.SO file needs to be in the OS's library search path for it to
-be found; simply placing it in the same directory as the executable won't
-necessarily work as it does on other platforms. The BASS libraries should
-also not be placed in the standard library directories to avoid version
-conflicts. To meet those competing requirements, a wrapper script could be
-used to set the "LD_LIBRARY_PATH" environment variable before loading the
-executable. Another option is to set the "rpath" in the executable, to tell
-it where to look for libraries. That is what the example makefiles do.
-
-When building both 32-bit and 64-bit executables, it is possible to simply
-try linking with both LIBBASS.SO versions, and the linker will use the
-appropriate version and ignore the other.
-
-Android version
----------------
-The BASS library includes support for use in Java and native code. The
-BASS.JAVA file mirrors BASS.H as much as possible, but there are some
-unavoidable differences, mainly in parameter/return types.
-
-When using ProGuard to obfuscate your Java code, the BASS classes should be
-left alone (see PROGUARD-BASS.PRO).
-
-See the example Android Studio project.
-
-iOS version
------------
-The BASS XCFramework should be added to the "Link Binary With Libraries" build
-phase in Xcode. If you're using an old Xcode version without XCFramework
-support then you can link directly with the library inside the XCFramework
-instead. Also add the following frameworks: Accelerate, AudioToolbox,
-AVFoundation, CFNetwork, SystemConfiguration. BASS does not include bitcode, so
-the "Enable Bitcode" option should be set to "No".
-
-
-Latest Version
-==============
-The latest version of BASS can always be found at the BASS website:
-
-	www.un4seen.com
-
-
-Licence
-=======
-BASS is free for non-commercial use. If you are a non-commercial entity
-(eg. an individual) and you are not making any money from your product
-(through sales/advertising/etc), then you can use BASS in it for free.
-If you wish to use BASS in commercial products, then please also see the
-next section.
-
-TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, BASS IS PROVIDED
-"AS IS", WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
-INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY
-AND/OR FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS SHALL NOT BE HELD
-LIABLE FOR ANY DAMAGE THAT MAY RESULT FROM THE USE OF BASS. YOU USE
-BASS ENTIRELY AT YOUR OWN RISK.
-
-Usage of BASS indicates that you agree to the above conditions.
-
-All trademarks and other registered names contained in the BASS
-package are the property of their respective owners.
-
-Commercial licensing
---------------------
-BASS is available for use in your commercial products. The licence
-types available are as follows:
-
-SHAREWARE: Allows the usage of BASS in an unlimited number of your
-shareware ("try before you buy") products, which must sell for no more
-than 40 Euros each. Non-shareware products are also permitted, but the
-product price limit is 10 Euros in that case. The price limit can be
-raised by purchasing duplicate licences, eg. 2 licences doubles it. If
-you are an individual (not a corporation) making and selling your own
-software, this is the licence for you. 
-
-SINGLE COMMERCIAL: Allows the usage of BASS in one commercial product.
-
-UNLIMITED COMMERCIAL: Allows the usage of BASS in an unlimited number
-of your commercial products. This licence is on a per-site basis, eg.
-if you are creating products with BASS at 2 sites/locations, then 2
-licences are required.
-
-Please note the products must be end-user products, eg. not components
-used by other products. 
-
-These licences only cover your own software, not the publishing of
-other's software. If you publish other's software, its developers (or
-the software itself) will need to be licensed to use BASS.
-
-These licences are on a per-platform basis, with reductions available
-when licensing for multiple platforms. In all cases there are no royalties
-to pay, and you can use future BASS updates without further cost.
-
-These licences do not allow reselling/sublicensing of BASS. For example,
-if a product is a development system, the users of said product are not
-licensed to use BASS in their productions; they will need their own
-licences.
-
-If the standard licences do not meet your requirements, or if you have
-any questions, please get in touch (email: bass@un4seen.com).
-
-Visit the BASS website for the latest pricing:
-
-	www.un4seen.com
-
-
-Credits
-=======
-Ogg Vorbis decoding is based on libogg/vorbis,
-Copyright (c) 2002-2020 Xiph.org Foundation
-
-CHMOX is (c) 2004 Stéphane Boisson, http://chmox.sourceforge.net/
-
-API/Sample contributors
------------------------
-Delphi: Titus Miloi, Rogier Timmermans, Alessandro Cappellozza,
-        Jesse Naranjo, Chris Troesken, Evgeny Melnikov
-Visual Basic: Adam Hoult, Hendrik Knaepen, Arthur Aminov,
-              Peter Hebels
-
-
-History
-=======
-These are the major (and not so major) changes at each version stage.
-There are of course bug fixes and other little improvements made along
-the way too! To make upgrading simpler, all functions affected by a
-change to the BASS interface are listed.
-
-2.4.16 - 24/6/2021
-------------------
-* DirectSound output mix is now generated by BASS (as with WASAPI output and
-  on other platforms), losing support for DirectSound-specific features but
-  gaining support for all BASS features
-	BASS_DEVICE_DSOUND (BASS_Init flag)
-* Length trimming
-	BASS_POS_END (BASS_ChannelSetPosition mode)
-	BASS_SYNC_END (BASS_ChannelSetSync type)
-	CUSTLOOP example updated
-* Custom loop start positions
-	BASS_POS_LOOP (BASS_ChannelSetPosition mode)
-	CUSTLOOP example updated
-* Length extending
-	BASS_ATTRIB_TAIL
-	BASS_SYNC_END (BASS_ChannelSetSync type)
-* Device reinitialization while retaining BASS channels and 3D settings
-	BASS_DEVICE_REINIT (BASS_Init flag)
-* Retrieval of a device's activity status
-	BASS_IsStarted
-* BASS_DEVICE_3D flag is no longer needed to enable 3D support
-	BASS_Init
-* The "Default" device is now enabled by default on Windows and macOS
-	BASS_CONFIG_DEV_DEFAULT (BASS_SetConfig option)
-* Default communications device indicator on Windows
-	BASS_DEVICE_DEFAULTCOM (BASS_DEVICEINFO flag)
-* Sample channel "newonly" option changed to a flag
-	BASS_SAMCHAN_NEW (BASS_SampleGetChannel flag)
-* Sample playback streams
-	BASS_SAMCHAN_STREAM (BASS_SampleGetChannel flag)
-	BASS_CTYPE_STREAM_SAMPLE
-* Speaker assignment support for samples
-	BASS_SampleGetChannel
-	BASS_ChannelFlags
-* Overriding of default flags during sample channel creation
-	BASS_SampleGetChannel
-* Same sample channel handle when max=1 is now optional
-	BASS_CONFIG_SAMPLE_ONEHANDLE (BASS_SetConfig option)
-* 3D max distance muting can now be toggled
-	BASS_SAMPLE_MUTEMAX (BASS_ChannelFlags flag)
-* Plugin disabling without affecting existing streams
-	BASS_PluginEnable
-* WASAPI recording on Windows (DirectSound is fallback/optional)
-	BASS_CONFIG_REC_WASAPI (BASS_SetConfig option)
-	BASS_RecordInit
-* Minimum recording buffer reduced to 10ms
-	BASS_CONFIG_REC_BUFFER (BASS_SetConfig option)
-* Recording data/level retrieval without removing from buffer when not using a RECORDPROC
-	BASS_DATA_NOREMOVE (BASS_ChannelGetData flag)
-	BASS_LEVEL_NOREMOVE (BASS_ChannelGetLevelEx flag)
-* Support for level measurements longer than 1s from decoding channels
-	BASS_ChannelGetLevelEx
-* Configurable restricted download rate
-	BASS_CONFIG_NET_RESTRATE (BASS_SetConfig option)
-* Thread-specific internet stream timeout options
-	BASS_CONFIG_THREAD (BASS_SetConfig option)
-	BASS_CONFIG_NET_TIMEOUT (BASS_SetConfig option)
-	BASS_CONFIG_NET_READTIMEOUT (BASS_SetConfig option)
-	BASS_StreamCreateURL
-* Configured "User-Agent" header can be overridden in custom request headers
-	BASS_StreamCreateURL
-* Multiple IPs will be tried when available on Linux/Android (already on other platforms)
-	BASS_StreamCreateURL
-* BASS_STREAM_BLOCK applied automatically on files larger than 2GB
-	BASS_StreamCreateURL/FileUser
-* Redirected URL retrieval
-	BASS_TAG_LOCATION (BASS_ChannelGetTags type)
-* Shoutcast metadata is now optional
-	BASS_CONFIG_NET_META (BASS_SetConfig option)
-	BASS_TAG_META (BASS_ChannelGetTags type)
-* Support for a 2nd ID3v2 tag block
-	BASS_TAG_ID3V2_2 (BASS_ChannelGetTags type)
-* OpenMPT channel name retrieval
-	BASS_TAG_MUSIC_CHAN (BASS_ChannelGetTags type)
-* Delayed OGG file scanning when prescanning is disabled/impossible
-	BASS_ChannelGetLength
-	BASS_ChannelSetPosition
-	BASS_CONFIG_OGG_PRESCAN (BASS_SetConfig option)
-* Faster seeking in large OGG files
-	BASS_ChannelSetPosition
-* Unified freeing function for all channel types
-	BASS_ChannelFree
-* User-defined attribute
-	BASS_ATTRIB_USER (BASS_ChannelSetAttributeEx option)
-* Push stream buffer size limiting
-	BASS_ATTRIB_PUSH_LIMIT (BASS_ChannelSetAttribute option)
-* Retrieval of a stream's available file data amount
-	BASS_FILEPOS_AVAILABLE (BASS_StreamGetFilePosition mode)
-* Error code for unsupported URL protocols
-	BASS_ERROR_PROTOCOL (BASS_StreamCreateURL error code)
-* BASS_ERROR_ALREADY error changed to success in some functions
-	BASS_ChannelPause
-	BASS_ChannelSetDevice
-	BASS_ChannelSetLink
-* Support for custom file streaming with Android Media codecs
-	BASS_StreamCreateFileUser
-* Switch to using native APIs for Android Media codecs (Android 5 or above required now)
-	BASS_StreamCreateFile/User/URL
-* BASS_TAG_AM_MIME value changed to fix conflict on Android
-	BASS_TAG_AM_MIME (BASS_ChannelGetTags type)
-* Improved support for single active input recording devices on Linux
-	BASS_RecordGetInputName
-	BASS_RecordGetInput
-	BASS_RecordSetInput
-* Automatic resumption of recordings after an interruption on iOS
-* Fix for Media Foundation AAC streaming with Windows 10 20H1
-	BASS_StreamCreateURL
-	BASS_StreamCreateFileUser
-* Fix for freeze when freeing a stream after BASS_ChannelSetLink failed with BASS_ERROR_ALREADY on it
-	BASS_ChannelSetLink
-* macOS examples rewritten in Objective-C/Cocoa
-* "MP3-FREE" version removed (MP3 patents expired)
-* armv5 (armeabi) architecture support dropped on Android
-
-2.4.15 - 17/12/2019
--------------------
-* Channel processing granularity option
-	BASS_ATTRIB_GRANULE (BASS_ChannelSetAttribute option)
-* Asynchronous mixtime sync callbacks
-	BASS_SYNC_THREAD (BASS_ChannelSetSync flag)
-* Output device update period can be set in samples
-	BASS_CONFIG_DEV_PERIOD (BASS_SetConfig option)
-* Continuous output when nothing is playing is now optional on macOS/iOS too
-	BASS_CONFIG_DEV_NONSTOP (BASS_SetConfig option)
-* AAudio output support on Android
-	BASS_Init
-	BASS_CONFIG_ANDROID_AAUDIO (BASS_SetConfig option)
-* Support for audio session IDs on Android
-	BASS_CONFIG_ANDROID_SESSIONID (BASS_SetConfig option)
-* ParcelFileDescriptor support on Android
-	BASS_StreamCreateFile
-	BASS_SampleLoad
-	BASS_MusicLoad
-* FloatValue Java class added to receive floating-point values on Android 10
-	BASS_Get3DFactors
-	BASS_RecordGetInput
-	BASS_ChannelGetAttribute
-	BASS_ChannelGet3DAttributes
-* Audio session configuration option on iOS
-	BASS_CONFIG_IOS_SESSION (BASS_SetConfig option)
-* OGG channel type constant renamed/duplicated to VORBIS
-	BASS_CTYPE_STREAM_VORBIS
-* Error code for recognised file formats without audio
-	BASS_ERROR_NOTAUDIO (BASS_StreamCreateFile/User/URL error code)
-* Error code for unstreamable MP4 files due to atom order
-	BASS_ERROR_UNSTREAMABLE (BASS_StreamCreateFileUser/URL error code)
-* Fix for AAC streaming with BASS_STREAM_BLOCK on macOS 10.15 and iOS 13
-	BASS_StreamCreateURL/FileUser
-* Fix for playback rate changing bug when using DirectSound
-	BASS_ATTRIB_FREQ (BASS_ChannelSetAttribute option)
-* armv6 architecture support dropped on iOS
-
-2.4.14 - 16/1/2019
-------------------
-* Support for playback on the "No sound" device
-	BASS_Init
-	BASS_StreamCreateFile/User/URL
-	BASS_SampleLoad/Create
-	BASS_ChannelPlay
-* Improved sample rate conversion quality, including 64 point option
-	BASS_ATTRIB_SRC (BASS_ChannelSetAttribute option)
-	BASS_CONFIG_SRC/_SAMPLE (BASS_SetConfig options)
-* Loopback (output device) recording on Windows Vista and above
-	BASS_RecordInit
-	BASS_RecordGetDeviceInfo
-	BASS_DEVICE_LOOPBACK (BASS_DEVICEINFO flag)
-	DEVLIST and RECTEST examples updated
-* Native format recording option
-	BASS_RecordStart
-* Access to the 3D output mix for applying DSP/FX
-	STREAMPROC_DEVICE_3D (BASS_StreamCreate option)
-* Retrieval of a device's started/stopped status
-	BASS_IsStarted
-* Sync for when a device stops unexpectedly
-	BASS_SYNC_DEV_FAIL (BASS_ChannelSetSync type)
-* New channel playback state for a paused device
-	BASS_ACTIVE_PAUSED_DEVICE (BASS_ChannelIsActive)
-* Sync for when a device's sample format changes
-	BASS_SYNC_DEV_FORMAT (BASS_ChannelSetSync type)
-* Adjustable output device update period
-	BASS_CONFIG_DEV_PERIOD (BASS_SetConfig option)
-* Nyquist FFT option
-	BASS_DATA_FFT_NYQUIST (BASS_ChannelGetData flag)
-* Plugin-specific flags are ignored in standard stream creation functions
-	BASS_StreamCreateFile/User/URL
-* Pre-buffering during stream creation is now disabled by default
-	BASS_CONFIG_NET_PREBUF_WAIT (BASS_SetConfig option)
-	BASS_StreamCreateURL/FileUser
-* Existing internet streams are unaffected by read timeout config changes
-	BASS_CONFIG_NET_READTIMEOUT (BASS_SetConfig option)
-* Retrieval of the number of existing handles
-	BASS_CONFIG_HANDLES (BASS_GetConfig option)
-* Windows mixer settings are retained by default and optionally not
-	BASS_CONFIG_WASAPI_PERSIST (BASS_SetConfig option)
-* Configurable OpenSSL library filename on Linux/Android
-	BASS_CONFIG_LIBSSL (BASS_SetConfigPtr option)
-* Files can be deleted/renamed while streaming on Windows (already true on other platforms)
-	BASS_StreamCreateFile
-* Fix for bug in playback buffering disabling option
-	BASS_ATTRIB_NOBUFFER (BASS_ChannelSetAttribute option)
-* Fix to support long logarithmic curves in volume effects
-	BASS_FX_VOLUME (BASS_ChannelSetFX type)
-
-2.4.13.8 - 6/2/2018
--------------------
-* Indication of a file's original sample format being floating-point
-	BASS_ORIGRES_FLOAT (BASS_CHANNELINFO/SAMPLE flag)
-* Some extra sample data is retained to account for device latency in data retrieval
-	BASS_ChannelGetData
-* FFT window is shortened to match amount of available data when less than FFT size
-	BASS_ChannelGetData
-* FFT level adjusted to be approx the same regardless of amount of available data
-	BASS_ChannelGetData
-* Fix for crash when decoding channels are dissociated from a device
-	BASS_NODEVICE (BASS_ChannelSetDevice option)
-
-2.4.13 - 19/12/2017
--------------------
-* WASAPI output on Windows (DirectSound is fallback/optional)
-	BASS_DEVICE_DSOUND (BASS_Init flag)
-	BASS_CONFIG_DEV_BUFFER/NONSTOP (BASS_SetConfig options)
-	BASS_CONFIG_SRC/_SAMPLE (BASS_SetConfig options)
-	BASS_ATTRIB_SRC/NORAMP (BASS_ChannelSetAttribute options)
-* Default output device following support extended to Windows Vista and macOS
-	BASS_CONFIG_DEV_DEFAULT (BASS_SetConfig option)
-* Seamless playback buffer length changing
-	BASS_ATTRIB_BUFFER (BASS_ChannelSetAttribute option)
-	SYNTH example updated
-* Access to the final output mix for applying DSP/FX
-	STREAMPROC_DEVICE (BASS_StreamCreate option)
-	BASS_CTYPE_STREAM_DEVICE
-	FXTEST example updated
-* Dissociating of decoding channels from a device
-	BASS_NODEVICE (BASS_ChannelSetDevice option)
-* Volume attribute levels above 1.0 for amplification
-	BASS_ATTRIB_VOL (BASS_ChannelSetAttribute option)
-* Logarithmic attribute slides
-	BASS_SLIDE_LOG (BASS_ChannelSlideAttribute flag)
-* Volume & panning attribute affected level retrieval
-	BASS_LEVEL_VOLPAN (BASS_ChannelGetLevelEx flag)
-* Volume level adjustment effect
-	BASS_FX_VOLUME (BASS_ChannelSetFX type)
-	BASS_FX_VOLUME_PARAM structure
-* Asynchronous pre-buffering
-	BASS_CONFIG_NET_PREBUF_WAIT (BASS_SetConfig option)
-	BASS_StreamCreateURL/FileUser
-	CONTEST and NETRADIO examples updated
-* Decoding channels can be dissociated from a device
-	BASS_ChannelSetDevice
-* Resetting of user file streams/decoders
-	BASS_POS_RESET (BASS_ChannelSetPosition flag)
-* Relative seeking
-	BASS_POS_RELATIVE (BASS_ChannelSetPosition flag)
-* RIFF cue points chunk retrieval
-	BASS_TAG_RIFF_CUE (BASS_ChannelGetTags type)
-	TAG_CUE structure
-* RIFF sample chunk retrieval
-	BASS_TAG_RIFF_SMPL (BASS_ChannelGetTags type)
-	TAG_SMPL structure
-* Support for Category/Description/Grouping/Keywords/Lyrics MP4 tags
-	BASS_TAG_MP4 (BASS_ChannelGetTags type)
-* Separate channel type for dummy streams
-	BASS_CTYPE_STREAM_DUMMY
-* Stalled internet stream buffering progress retrieval
-	BASS_FILEPOS_BUFFERING (BASS_StreamGetFilePosition mode)
-	CONTEST and NETRADIO examples updated
-* Playlist recursion depth config option
-	BASS_CONFIG_NET_PLAYLIST_DEPTH (BASS_SetConfig options)
-* Push file system read functions can now return 0 without ending the file
-	STREAMFILE_BUFFERPUSH (BASS_StreamCreateFileUser system)
-	FILEREADPROC
-* 16 point SRC is used by default when SSE is available
-	BASS_CONFIG_SRC (BASS_SetConfig option)
-* Mono downmixing for all file formats in sample loading
-	BASS_SAMPLE_MONO (BASS_SampleLoad flag)
-* Mono OGG stream downmixing
-	BASS_SAMPLE_MONO (BASS_StreamCreateFile/User/URL flag)
-* Media Foundation availability detection
-	BASS_CONFIG_MF_DISABLE (BASS_GetConfig option)
-	PLUGINS example updated
-* AudioTrack output on Android
-	BASS_DEVICE_AUDIOTRACK (BASS_Init flag)
-* Support for Android Media codecs
-	BASS_StreamCreateFile/User/URL
-	BASS_TAG_AM_MIME/NAME (BASS_ChannelGetTags type)
-	BASS_CONFIG_AM_DISABLE (BASS_SetConfig option)
-* Panning fix for MOD files created with ScreamTracker 3
-	BASS_MusicLoad
-* Fix for compressor and distotion DX8 effects with floating-point data on Windows
-	BASS_FX_DX8_COMPRESSOR/DISTORTION (BASS_ChannelSetFX types)
-* Fix for plugin freeing issue on 64-bit platforms (HPLUGIN is not library address any more)
-	BASS_PluginLoad
-	BASS_PluginFree
-
-2.4.12 - 10/3/2016
-------------------
-* DSP/FX chain order modification
-	BASS_FXSetPriority
-* Average bitrate retrieval
-	BASS_ATTRIB_BITRATE
-* Ramping-out when stopping/pausing playback
-	BASS_ChannelStop
-	BASS_ChannelPause
-* Disabling of playback ramping
-	BASS_ATTRIB_NORAMP (BASS_ChannelSetAttribute option)
-* Pre-buffering when playback buffering is disabled
-	BASS_ChannelUpdate
-	BASS_ATTRIB_NOBUFFER (BASS_ChannelSetAttribute option)
-* Net agent and proxy config options now make a copy of the provided string
-	BASS_CONFIG_NET_AGENT/PROXY (BASS_SetConfigPtr options)
-	NETRADIO example updated
-* Unicode net agent and proxy config options on Windows
-	BASS_CONFIG_NET_AGENT/PROXY (BASS_SetConfigPtr options)
-* 32768 sample FFT
-	BASS_DATA_FFT32768 (BASS_ChannelGetData flag)
-* Support for iTunes gapless info in MP3 files
-	BASS_StreamCreateFile/User
-* 529 sample delay removed from start of MP3 files without delay info
-	BASS_StreamCreateFile/User/URL
-* Support for numerical MP4 genre (gnre) tags
-	BASS_TAG_MP4 (BASS_ChannelGetTags type)
-* Support for BASSWMA's tag option when using Media Foundation WMA codec
-	BASS_TAG_WMA (BASS_ChannelGetTags type)
-* OpenMPT author tag retrieval
-	BASS_TAG_MUSIC_AUTH (BASS_ChannelGetTags type)
-* FastTracker2 panning for XM files
-	BASS_MUSIC_FT2PAN (BASS_MusicLoad flag)
-* Support for longer device names on Windows
-	BASS_DEVICEINFO (name member)
-* Checking for floating-point support on platforms that might not have it
-	BASS_CONFIG_FLOAT (BASS_GetConfig option)
-* Attribute size retrieval fix
-	BASS_ChannelGetAttributeEx
-* Fix for missing LC_VERSION_MIN issue with Xcode 7 on OSX, ppc architecture (PowerPC) support dropped
-* LIST example renamed to DEVLIST
-
-2.4.11 - 22/12/2014
--------------------
-* Support for custom HTTP request headers
-	BASS_StreamCreateURL
-* HTTPS support on Linux/Android
-	BASS_StreamCreateURL
-* Redirection HTTP headers provided during connection
-	BASS_STREAM_STATUS (BASS_StreamCreateURL flag)
-	DOWNLOADPROC
-* Adjustable stalled internet stream resumption buffer level
-	BASS_ATTRIB_NET_RESUME (BASS_ChannelSetAttribute option)
-* Extended level retrieval inc. multi-channel and RMS options
-	BASS_ChannelGetLevelEx
-* Inexact/faster seeking
-	BASS_POS_INEXACT (BASS_ChannelSetPosition flag)
-* Post-stream creation scanning (seek table building)
-	BASS_POS_SCAN (BASS_ChannelSetPosition flag)
-* Extended attribute support
-	BASS_ChannelGet/SetAttributeEx
-* Scanned info retrieval and setting
-	BASS_ATTRIB_SCANINFO (BASS_ChannelGet/SetAttributeEx option)
-* Built-in ADPCM WAVE file support on Linux/Android/WinCE
-	BASS_StreamCreateFile/User/URL
-	BASS_SampleLoad
-* Active MOD channel count retrieval
-	BASS_ATTRIB_MUSIC_ACTIVE (BASS_ChannelGetAttribute option)
-* Fractional sample rates
-	BASS_ATTRIB_FREQ (BASS_ChannelSetAttribute option)
-* Device type information
-	BASS_DEVICE_TYPE_xxx (BASS_DEVICEINFO flags)
-* Unicode support for recording input names
-	BASS_CONFIG_UNICODE (BASS_SetConfig option)
-	BASS_RecordGetInputName
-* File size retrieval
-	BASS_FILEPOS_SIZE (BASS_StreamGetFilePosition mode)
-* Asynchronous file reading buffer level retrieval
-	BASS_FILEPOS_ASYNCBUF (BASS_StreamGetFilePosition mode)
-* MPEG data search limit raised to 1MB
-	BASS_CONFIG_VERIFY (BASS_SetConfig option)
-* Separate MPEG data search limit for internet/buffered streams
-	BASS_CONFIG_VERIFY_NET (BASS_SetConfig option)
-* Support for iTunes gapless info with Media Foundation and CoreAudio codecs
-	BASS_StreamCreateFile/User
-* Airplay receiver enumeration and selection on OSX
-	BASS_DEVICES_AIRPLAY (BASS_GetDeviceInfo flag)
-	BASS_CONFIG_AIRPLAY (BASS_SetConfig option)
-* Media Foundation playback of audio from videos is now optional
-	BASS_CONFIG_MF_VIDEO (BASS_SetConfig option)
-* Optional floating-point or fixed-point data retrieval on Android/WinCE
-	BASS_DATA_FLOAT/FIXED (BASS_ChannelGetData flags)
-* Continuous output when nothing is playing on Linux/Android/WinCE
-	BASS_CONFIG_DEV_NONSTOP (BASS_SetConfig option)
-* Fix for decoding channels being ended when stopping the output device
-	BASS_Stop
-* Fix for Media Foundation internet/buffered streaming on Windows 8
-	BASS_StreamCreateURL
-	BASS_StreamCreateFileUser
-* Improved compatibility with recent PulseAudio versions on Linux
-* LIST and MODTEST examples added
-* MASM API and examples removed (available as separate download)
-
-2.4.10 - 16/2/2013
-------------------
-* Asynchronous file reading/buffering
-	BASS_ASYNCFILE (BASS_StreamCreateFile/User flag)
-	BASS_CONFIG_ASYNCFILE_BUFFER (BASS_SetConfig option)
-* Support for chained OGG files (multiple logical bitstreams)
-	BASS_StreamCreateFile/User
-	BASS_CONFIG_OGG_PRESCAN (BASS_SetConfig option)
-	BASS_POS_OGG (BASS_ChannelSetPosition/ChannelGetLength mode)
-* OGG logical bitstream syncs are no longer automatically "mixtime"
-	BASS_SYNC_OGG_CHANGE (BASS_ChannelSetSync type)
-* Support for Soundtracker MOD files
-	BASS_MusicLoad
-* Complex FFT data
-	BASS_DATA_FFT_COMPLEX (BASS_ChannelGetData flag)
-* Volume levels above 1.0 for decoding channels
-	BASS_ATTRIB_VOL (BASS_ChannelSetAttribute option)
-* Recording device channel count retrieval on Windows/OSX/iOS
-	BASS_RECORDINFO (formats member)
-* Minimum recording period reduced to 5ms
-	BASS_RecordStart
-* Recording device period adjustment on OSX
-	BASS_RecordStart
-* Device UID retrieval on OSX
-	BASS_DEVICEINFO (driver member)
-* The desktop window handle is used when none is provided
-	BASS_Init
-
-2.4.9 - 3/5/2012
-----------------
-* Improved and adjustable sample rate conversion quality
-	BASS_ATTRIB_SRC (BASS_ChannelSetAttribute option)
-	BASS_CONFIG_SRC/_SAMPLE (BASS_SetConfig options)
-* Support for buffered file & internet streams with CoreAudio codecs on OSX/iOS
-	BASS_StreamCreateURL
-	BASS_StreamCreateUser
-* Data and level retrieval from sample channels
-	BASS_ChannelGetData
-	BASS_ChannelGetLevel
-* Oldest sample channel will be overridden when there are multiple candidates
-	BASS_SampleGetChannel
-* Use of the device's output rate with MODs
-	BASS_MusicLoad
-* Optional device output rate setting on OSX/iOS
-	BASS_DEVICE_FREQ (BASS_Init flag)
-* UTF-8 device information on Windows
-	BASS_CONFIG_UNICODE (BASS_SetConfig option)
-* Speaker assignment with panning/balance control on Windows Vista/7
-	BASS_CONFIG_VISTA_SPEAKERS (BASS_SetConfig option)
-	BASS_ATTRIB_PAN (BASS_ChannelGet/Set/SlideAttribute option)
-* Push stream queue level can be checked after using BASS_STREAMPROC_END
-	BASS_StreamPutData
-* Support for ALSA subdevices on Linux
-	BASS_Init
-	BASS_GetDeviceInfo
-	BASS_RecordInit
-	BASS_RecordGetDeviceInfo
-* Device list fix on 64-bit OSX
-	BASS_GetDeviceInfo
-	BASS_RecordGetDeviceInfo
-* BASS_UNICODE support fix on Linux
-	BASS_PluginLoad
-* Internet streaming tweaks/fixes on Windows
-* SYNTH example updated to use device output rate
-* RECTEST example updated (C version) for better Windows Vista/7 support
-* Documentation updated with platform-specific info for Android
-
-2.4.8 - 29/8/2011
------------------
-* Support for Media Foundation codecs on Windows 7 and updated Vista
-	BASS_StreamCreateFile/User/URL
-	BASS_TAG_MF (BASS_ChannelGetTags type)
-	PLUGINS example updated
-* Built-in support for MP4 tags on Win32/OSX/iOS (for Media Foundation & CoreAudio AAC/ALAC codecs)
-	BASS_TAG_MP4 (BASS_ChannelGetTags type)
-* WAVE format chunk retrieval
-	BASS_TAG_WAVEFORMAT (BASS_ChannelGetTags type)
-* Adjustable sample channel limit
-	BASS_SampleSetInfo
-* Per-channel CPU usage monitoring
-	BASS_ATTRIB_CPU (BASS_ChannelGetAttribute option)
-* Pre-allocation of push stream queue space
-	BASS_StreamPutData
-* Support for AIFF files with the data chunk before the format info chunk
-	BASS_StreamCreateFile/User/URL
-* Ramping-in disabled for all but the XM format (and MODs in FT2 mode) in "normal" ramping mode
-	BASS_MUSIC_RAMP (BASS_MusicLoad flag)
-* RIFF "INFO" tag reading fix
-	BASS_TAG_RIFF_INFO (BASS_ChannelGetTags type)
-* OSX 10.7 compatibility fix
-* x86_64 architecture support on OSX
-* Delphi dynamic loading unit removed (now available as separate download)
-
-2.4.7 - 30/11/2010
-------------------
-* Decode-to-position seeking
-	BASS_POS_DECODETO (BASS_ChannelSetPosition flag)
-* Support for RIFF "DISP" text tags
-	BASS_TAG_RIFF_DISP (BASS_ChannelGetTags type)
-* Support for APEv1 tags
-	BASS_TAG_APE (BASS_ChannelGetTags type)
-	BASS_TAG_APE_BINARY (BASS_ChannelGetTags type)
-* 16384 sample FFT
-	BASS_DATA_FFT16384 (BASS_ChannelGetData flag)
-* Support for AIFF files larger than 4GB
-	BASS_StreamCreateFile/User/URL
-* Acceptance of self-signed and invalid certificates
-	BASS_StreamCreateURL
-* Internet stream reading timeout
-	BASS_CONFIG_NET_READTIMEOUT (BASS_SetConfig option)
-* Support for removing a DSP within its DSPPROC
-	BASS_ChannelRemoveDSP
-* Buffer bypassing for lower latency output (not available on Windows)
-	BASS_ATTRIB_NOBUFFER (BASS_ChannelSetAttribute option)
-	SYNTH example added (OSX)
-* A "Default" device that follows default device changes on Windows 7
-	BASS_CONFIG_DEV_DEFAULT (BASS_SetConfig option)
-* Xcode examples project added for OSX
-* Documentation updated with platform-specific info for iOS/Linux/WinCE
-
-2.4.6 - 17/6/2010
------------------
-* Support for APEv2 tags, including binary
-	BASS_TAG_APE (BASS_ChannelGetTags type)
-	BASS_TAG_APE_BINARY (BASS_ChannelGetTags type)
-* Unicode/IDN URL support
-	BASS_StreamCreateURL
-* Decoding position retrieval
-	BASS_POS_DECODE (BASS_ChannelGetPosition flag)
-* Support for OGG 6/7.1 channel configs
-	BASS_StreamCreateFile/User/URL
-* Support for setting syncs within mixtime SYNCPROCs
-	BASS_ChannelSetSync
-* Support for setting additional DSP/FX within DSPPROCs
-	BASS_ChannelSetDSP/FX
-* DC bias removal in FFT processing
-	BASS_DATA_FFT_REMOVEDC (BASS_ChannelGetData flag)
-* Fix for incorrect (2x) return value when getting FFT data from a 16-bit channel
-	BASS_ChannelGetData
-* Fix for incorrect (STOPPED instead of PAUSED) channel status following BASS_Pause
-	BASS_ChannelIsActive
-
-2.4.5 - 18/12/2009
-------------------
-* Support for little-endian AIFF files
-	BASS_StreamCreateFile/User/URL
-	BASS_SampleLoad
-* Support for 64-bit floating-point WAVE/AIFF files
-	BASS_StreamCreateFile/User/URL
-	BASS_SampleLoad
-* Input volume retrieval failure results in a reading of -1 instead of 1
-	BASS_RecordGetInput
-	RECTEST example updated
-* Input volume support on OSX
-	BASS_RecordSetInput
-	BASS_RecordGetInput
-	RECTEST example updated
-* Fix for deferred input settings on Vista
-	BASS_RecordSetInput
-* Windows MP3 codec given preference over other installed MP3 codecs (MP3-FREE version)
-	BASS_StreamCreateFile/User/URL
-	BASS_SampleLoad
-
-2.4.4 - 13/10/2009
-------------------
-* RIFF/BWF "radio traffic" tag retrieval
-	BASS_TAG_RIFF_CART (BASS_ChannelGetTags type)
-	TAG_CART structure
-* Support for ID3v2 tags in RIFF/WAVE/AIFF files ("ID3 " chunk)
-	BASS_TAG_ID3V2 (BASS_ChannelGetTags type)
-* Pushed fractional samples are refused rather than discarded
-	BASS_StreamPutData
-* DX8 effect emulation on OSX
-	BASS_FX_DX8_CHORUS/DISTORTION/ECHO/FLANGER/PARAMEQ/REVERB (BASS_ChannelSetFX types)
-	FXTEST example added
-* UTF-16 support on OSX
-	BASS_UNICODE (BASS_StreamCreateFile/SampleLoad/MusicLoad/PluginLoad flag)
-
-2.4.3 - 8/5/2009
-----------------
-* MOD order list retrieval
-	BASS_TAG_MUSIC_ORDERS (BASS_ChannelGetTags type)
-* Support for ID3v2 tags in RIFF/WAVE files ("id3 " chunk)
-	BASS_TAG_ID3V2 (BASS_ChannelGetTags type)
-* Improved position reporting precision on Vista
-	BASS_ChannelGetPosition
-* Length retrieval when streaming in blocks (BASS_STREAM_BLOCK)
-	BASS_ChannelGetLength
-* Support for CoreAudio codecs on OSX
-	BASS_StreamCreateFile/User
-	BASS_SampleLoad
-	BASS_TAG_CA_CODEC (BASS_ChannelGetTags type)
-	TAG_CA_CODEC structure
-* 3D algorithm option support on OSX
-	BASS_CONFIG_3DALGORITHM (BASS_SetConfig option)
-
-2.4.2 - 18/9/2008
------------------
-* RF64 support
-	BASS_StreamCreateFile/User
-* RIFF/BWF "Broadcast Audio Extension" tag retrieval
-	BASS_TAG_RIFF_BEXT (BASS_ChannelGetTags type)
-	TAG_BEXT structure
-* ID3v1 tag structure
-	TAG_ID3 structure
-* Multiple simultaneous recordings per device on Vista & OSX (as on XP)
-	BASS_RecordStart
-* DX8 effect parameter defaults updated/corrected in documentation
-
-2.4 - 2/4/2008
---------------
-* "Push" streaming
-	STREAMPROC_PUSH (BASS_StreamCreate option)
-	BASS_StreamPutData
-	LIVEFX and MULTI examples updated
-* "Push" buffered file streaming
-	STREAMFILE_BUFFERPUSH (BASS_StreamCreateFileUser system)
-	BASS_StreamPutFileData
-* STREAMFILEPROC replaced by table of callbacks for each file operation
-	BASS_FILEPROCS (FILECLOSEPROC/FILELENPROC/FILEREADPROC/FILESEEKPROC)
-	STREAMFILEPROC *removed*
-* 64-bit file positioning
-	BASS_SampleLoad
-	BASS_MusicLoad
-	BASS_StreamCreateFile
-	BASS_StreamGetFilePosition
-* File buffer level retrieval
-	BASS_FILEPOS_BUFFER (BASS_StreamGetFilePosition mode)
-* Sinc interpolated MOD music mixing
-	BASS_MUSIC_SINCINTER (BASS_MusicLoad flag)
-* MO3 2.4 support
-	BASS_MusicLoad
-* MOD orders positioning incorporated into channel functions
-	BASS_ChannelGetLength
-	BASS_ChannelSetPosition
-	BASS_ChannelGetPosition
-	BASS_MusicGetOrderPosition *removed*
-	BASS_MusicGetOrders *removed*
-* Channel attribute functions consolidated
-	BASS_ChannelSetAttribute
-	BASS_ChannelGetAttribute
-	BASS_ChannelSlideAttribute
-	BASS_ChannelIsSliding
-	BASS_ChannelSetAttributes *removed*
-	BASS_ChannelGetAttributes *removed*
-	BASS_ChannelSlideAttributes *removed*
-	BASS_ChannelSetEAXMix *removed*
-	BASS_ChannelGetEAXMix *removed*
-	BASS_MusicSetAttribute *removed*
-	BASS_MusicGetAttribute *removed*
-* Floating-point volume and panning
-	BASS_SetVolume
-	BASS_GetVolume
-	BASS_RecordSetInput
-	BASS_RecordGetInput
-	BASS_ATTRIB_PAN/VOL (BASS_ChannelGet/Set/SlideAttribute options)
-	BASS_ATTRIB_MUSIC_VOL_CHAN/INST (BASS_ChannelGet/Set/SlideAttribute options)
-	BASS_SAMPLE (volume/pan/outvol members)
-	BASS_CONFIG_MAXVOL *removed*
-	BASSTEST and RECTEST examples updated
-* Output device volume control on Vista (as on other OS)
-	BASS_SetVolume
-	BASS_GetVolume
-* Multiple update threads
-	BASS_CONFIG_UPDATETHREADS (BASS_SetConfig option)
-	BASSTEST example updated
-* Global volume range increased to 10000
-	BASS_CONFIG_GVOL_SAMPLE/STREAM/MUSIC (BASS_SetConfig options)
-	BASSTEST example updated
-* Setting and retrieving of a sample's data
-	BASS_SampleSetData
-	BASS_SampleGetData
-	BASS_SampleCreate
-	BASS_SampleCreateDone *removed*
-* Channel flag setting mask
-	BASS_ChannelFlags
-	BASS_ChannelSetFlags *removed*
-	SPEAKERS example updated
-* 256 sample FFT
-	BASS_DATA_FFT256 (BASS_ChannelGetData flag)
-* Channel locking to prevent access by other threads
-	BASS_ChannelLock
-* Manual channel buffer updating
-	BASS_ChannelUpdate
-	BASS_ChannelPreBuf *removed*
-* Configurable manual update length
-	BASS_Update
-* Extended device information retrieval and detection of new/removed devices
-	BASS_GetDeviceInfo
-	BASS_RecordGetDeviceInfo
-	BASS_DEVICEINFO structure
-	BASS_GetDeviceDescription *removed*
-	BASS_RecordGetDeviceDescription *removed*
-	BASS_INFO (driver member) *removed*
-	BASS_RECORDINFO (driver member) *removed*
-	MULTI example updated
-* Default device change tracking on Windows (as on OSX)
-	BASS_Init
-	BASS_RecordInit
-* Speaker detection from Windows control panel
-	BASS_DEVICE_CPSPEAKERS (BASS_Init flag)
-* Channel automatically stopped & resumed for DX8 effects
-	BASS_ChannelSetFX
-	BASS_ChannelRemoveFX
-* "double" precision position conversion
-	BASS_ChannelBytes2Seconds
-	BASS_ChannelSeconds2Bytes
-* Separate config functions for pointers
-	BASS_SetConfigPtr
-	BASS_GetConfigPtr
-	BASS_CONFIG_NET_AGENT/PROXY (BASS_SetConfigPtr options)
-* Configurable file format verification length
-	BASS_CONFIG_VERIFY (BASS_SetConfig option)
-* Stream filename retrieval
-	BASS_CHANNELINFO (file member)
-* Channel sample retrieval
-	BASS_CHANNELINFO (sample member)
-* META syncs no longer receive metadata in the "data" parameter
-	BASS_SYNC_META (BASS_ChannelSetSync type)
-* Separate sync for OGG logical bitstream changes (instead of BASS_SYNC_META)
-	BASS_SYNC_OGG_CHANGE (BASS_ChannelSetSync type)
-	NETRADIO example updated (C version)
-* Message syncing removed (use PostMessage instead)
-	BASS_SYNC_MESSAGE (BASS_ChannelSetSync flag) *removed*
-* Data retrieval from stopped/paused channels
-	BASS_ChannelGetData
-* Callback "user" parameters changed to pointers
-	BASS_StreamCreate / STREAMPROC
-	BASS_StreamCreateFileUser
-	BASS_StreamCreateURL / DOWNLOADPROC
-	BASS_RecordStart / RECORDPROC
-	BASS_ChannelSetDSP / DSPPROC
-	BASS_ChannelSetSync / SYNCPROC
-
-2.3.0.3 - 30/7/2007
--------------------
-* FX state resetting
-	BASS_FXReset
-* PLS/M3U playlist URL processing
-	BASS_CONFIG_NET_PLAYLIST (BASS_SetConfig option)
-	NETRADIO example updated
-* Internet stream connection status retrieval
-	BASS_FILEPOS_CONNECTED (BASS_StreamGetFilePosition mode)
-* Lyrics3v2 tags
-	BASS_TAG_LYRICS3 (BASS_ChannelGetTags type)
-* IT virtual channel configuration
-	BASS_CONFIG_MUSIC_VIRTUAL (BASS_SetConfig option)
-* Accurate speaker detection on Vista
-	BASS_INFO (speakers member)
-* Device output/input rate retrieval on Vista
-	BASS_INFO (freq member)
-	BASS_RECORDINFO (freq member)
-* Syncing upon position changes
-	BASS_SYNC_SETPOS (BASS_ChannelSetSync type)
-* Improved stall handling
-	BASS_SYNC_STALL
-* Invalid decoding channel flags produce an error instead of being ignored
-	BASS_StreamCreate/File/User/URL
-	BASS_MusicLoad
-
-2.3.0.2 - 22/1/2007
--------------------
-* Retrieval of a sample's existing channel handles
-	BASS_SampleGetChannels
-* 8192 sample FFT
-	BASS_DATA_FFT8192 (BASS_ChannelGetData flag)
-* Adjustable recording buffer
-	BASS_CONFIG_REC_BUFFER (BASS_SetConfig option)
-* Stopping decoding channels before the end
-	BASS_ChannelStop
-* Sample channels created paused to prevent overriding before playback
-	BASS_SampleGetChannel
-* Separate "MP3-FREE" version using the OS's MP3 decoder
-	BASS_CONFIG_MP3_CODEC *removed*
-
-2.3.0.1 - 12/6/2006
--------------------
-* Ability to move a channel to another device
-	BASS_ChannelSetDevice
-	MULTI example updated
-* Support for ID3v2.4 tags at end of file
-	BASS_TAG_ID3V2 (BASS_ChannelGetTags type)
-
-2.3 - 21/5/2006
----------------
-* MOD message/instrument/sample text retrieval, merged with stream tag retrieval function
-	BASS_ChannelGetTags
-	BASS_TAG_MUSIC_NAME/MESSAGE/INST/SAMPLE (BASS_ChannelGetTags types)
-	BASS_MusicGetName *removed*
-	BASS_StreamGetTags *removed*
-* Plugin information retrieval
-	BASS_PluginGetInfo
-	BASS_PLUGININFO/FORM structures
-	BASS_CHANNELINFO (plugin member)
-	PLUGINS example updated
-* RIFF/WAVE "INFO" tag retrieval
-	BASS_TAG_RIFF_INFO (BASS_StreamGetTags type)
-* More specific WAVE format information
-	BASS_CTYPE_STREAM_WAV_PCM/FLOAT (channel types)
-	BASS_CTYPE_STREAM_WAV (channel type flag)
-* Proxy server configuration
-	BASS_CONFIG_NET_PROXY (BASS_SetConfig option)
-	BASS_CONFIG_NET_NOPROXY *removed*
-	NETRADIO example updated
-* Passive FTP mode
-	BASS_CONFIG_NET_PASSIVE (BASS_SetConfig option)
-* Agent changes take immediate effect
-	BASS_CONFIG_NET_AGENT (BASS_SetConfig option)
-* Minimum time gap between creating new sample channels
-	BASS_SAMPLE (mingap member)
-	BASS_SampleGetChannel
-* Support for Unicode plugin filenames
-	BASS_PluginLoad
-* Device output/input rate retrieval (MacOSX only)
-	BASS_INFO (freq member)
-	BASS_RECORDINFO (freq member)
-* Extended version info (minor revision)
-	BASS_GetVersion
-* Unsupported codec error code
-	BASS_ERROR_CODEC
-* Optional use of the Windows MP3 codec
-	BASS_CONFIG_MP3_CODEC (BASS_SetConfig option)
-* 3D support for MacOSX
-	BASS_Set3DFactors
-	BASS_Get3DFactors
-	BASS_Set3DPosition
-	BASS_Get3DPosition
-	BASS_Apply3D
-	BASS_ChannelSet3DAttributes
-	BASS_ChannelGet3DAttributes
-	BASS_ChannelSet3DPosition
-	BASS_ChannelGet3DPosition
-	3DTEST example added (Win32 example also updated)
-* VB version of SYNTH example added
-
-2.2 - 2/10/2005
----------------
-* Add-on plugin system
-	BASS_PluginLoad
-	BASS_PluginFree
-	BASS_StreamCreateFile/User/URL
-	BASS_SampleLoad
-	PLUGINS example added
-* MOD position & syncing in bytes
-	BASS_ChannelSetPosition
-	BASS_ChannelGetPosition
-	BASS_MusicGetOrderPosition added for orders position
-	BASS_SYNC_MUSICPOS added for orders syncing
-	MAKEMUSICPOS macro/define
-	CUSTLOOP example updated
-* Stream/MOD "length" functions combined (also works with samples), new MOD orders length function
-	BASS_ChannelGetLength
-	BASS_MusicGetOrders
-	BASS_StreamGetLength *removed*
-	BASS_MusicGetLength *removed*
-* Support for AIFF files
-	BASS_StreamCreateFile/User/URL
-	BASS_SampleLoad
-* Support for 24 and 32-bit (integer) WAV files
-	BASS_StreamCreateFile/User/URL
-	BASS_SampleLoad
-* WAV files are no longer converted to the "device" resolution
-	BASS_StreamCreateFile/User/URL
-* Recording master control
-	BASS_RecordGetInput
-	BASS_RecordSetInput
-* Adjustable pre-buffering
-	BASS_ChannelPreBuf
-* Floating-point data retrieval
-	BASS_DATA_FLOAT (BASS_ChannelGetData flag)
-* Support for floating-point samples
-	BASS_SampleLoad
-	BASS_SampleCreate
-* Multi-channel samples
-	BASS_SampleLoad/Create
-	BASS_SAMPLE (chans member)
-* Sample lengths given in bytes
-	BASS_SampleCreate
-	BASS_SAMPLE (length member)
-* MOD music 8-bit resolution option
-	BASS_MusicLoad
-* OGG vendor tag retrieval
-	BASS_TAG_VENDOR (BASS_StreamGetTags type)
-* Configurable "User-Agent" header for internet streams
-	BASS_CONFIG_NET_AGENT (BASS_SetConfig option)
-* Shoutcast metadata is now requested automatically
-	BASS_STREAM_META flag *removed*
-* Download callbacks receive all data from start of file/stream (including any non-audio data)
-	DOWNLOADPROC
-* Length when streaming in blocks is unavailable (BASS_ERROR_NOTAVAIL, not just 0)
-	BASS_ChannelGetLength
-* Support for growing custom file streams
-	BASS_FILE_LEN (STREAMFILEPROC action)
-* Query file action removed
-	BASS_FILE_QUERY *removed*
-* Recording channel syncing
-	BASS_ChannelSetSync
-* Info structure "size" members removed
-	BASS_INFO structure
-	BASS_RECORDINFO structure
-* Little bit of flag reshuffling
-	BASS_MP3_SETPOS renamed to BASS_STREAM_PRESCAN
-	BASS_MUSIC_CALCLEN value changed and renamed to BASS_MUSIC_PRESCAN
-	BASS_MUSIC_POSRESET value changed
-* Add-on API enhancements
-* MacOSX port introduced
-
-2.1 - 28/11/2004
-----------------
-* Improved "mixtime" sync system, allowing custom looping
-	SYNCPROC
-	CUSTLOOP example added
-* FX can now be in the DSP chain, so can be prioritized and applied in floating-point
-	BASS_ChannelSetFX
-	BASS_CONFIG_FLOATDSP (BASS_SetConfig option)
-* Ability to set channel flags (eg. looping) independent of playback
-	BASS_ChannelSetFlags
-	SPEAKERS example updated
-* Stream/MOD "play" and channel "resume" functions combined
-	BASS_ChannelPlay
-	BASS_StreamPlay *removed*
-	BASS_MusicPlay *removed*
-	BASS_MusicPlayEx *removed*
-	BASS_ChannelResume *removed*
-* Stream/MOD pre-buffering functions combined
-	BASS_ChannelPreBuf
-	BASS_StreamPreBuf *removed*
-	BASS_MusicPreBuf *removed*
-* MOD attribute functions combined, with added BPM/speed/globalvolume options
-	BASS_MusicSetAttribute
-	BASS_MusicGetAttribute
-	BASS_MUSIC_ATTRIB_AMPLIFY
-	BASS_MUSIC_ATTRIB_PANSEP
-	BASS_MUSIC_ATTRIB_PSCALER
-	BASS_MUSIC_ATTRIB_BPM
-	BASS_MUSIC_ATTRIB_SPEED
-	BASS_MUSIC_ATTRIB_VOL_GLOBAL
-	BASS_MUSIC_ATTRIB_VOL_CHAN
-	BASS_MUSIC_ATTRIB_VOL_INST
-	BASS_MusicSetAmplify *removed*
-	BASS_MusicSetPanSep *removed*
-	BASS_MusicSetPositionScaler *removed*
-	BASS_MusicSetVolume *removed*
-	BASS_MusicGetVolume *removed*
-* Flag to reset bpm/etc as well as notes when seeking in MOD musics
-	BASS_MUSIC_POSRESETEX (BASS_MusicLoad & BASS_ChannelSetFlags flag)
-* More flexible and concise sample channel creation system
-	BASS_SampleGetChannel
-	BASS_SamplePlay *removed*
-	BASS_SamplePlayEx *removed*
-	BASS_SamplePlay3D *removed*
-	BASS_SamplePlay3DEx *removed*
-* Support for up to 30 speakers
-	BASS_SPEAKER_N macro/define
-* More precise level measurement
-	BASS_ChannelGetLevel
-* Level can now be retrieved from decoding channels
-	BASS_ChannelGetLevel
-* Retrieval of a sample/channel's original sample resolution
-	BASS_SAMPLE (origres member)
-	BASS_CHANNELINFO (origres member)
-* Support for streaming WAV files in "blocks"
-	BASS_StreamCreateURL
-	BASS_StreamCreateFileUser
-* Status info (HTTP/ICY tags) available during connection to server
-	BASS_STREAM_STATUS (BASS_StreamCreateURL flag)
-	DOWNLOADPROC
-	NETRADIO example updated (Delphi version also added)
-* Adjustable internet stream pre-buffering
-	BASS_CONFIG_NET_PREBUF (BASS_SetConfig option)
-* Option to bypass proxy server
-	BASS_CONFIG_NET_NOPROXY (BASS_SetConfig option)
-* Option whether to allow channels to be played after BASS_Pause
-	BASS_CONFIG_PAUSE_NOPLAY (BASS_SetConfig option)
-* Recording channel count now a separate parameter
-	BASS_RecordStart (chans parameter)
-* Synchronizer for when a channel is freed
-	BASS_SYNC_FREE (BASS_ChannelSetSync type)
-* Data start file position retrieval
-	BASS_FILEPOS_START (BASS_StreamGetFilePosition mode)
-* Performance improvements
-	MP2 decoding ~20% faster
-	MP3/MP1 decoding & FFT processing all up to 10% faster
-	OGG decoding ~3% faster
-* C/C++ examples reorganised, with makefiles & VC++ projects
-* Add-on API enhancements
-* More DLL shrinkage :)
-
-2.0 - 31/10/2003
-----------------
-* Multiple output device support
-	BASS_Init (device number changes)
-	BASS_SetDevice
-	BASS_GetDevice
-	BASS_ChannelGetDevice
-	MULTI example updated (VB version also added)
-* Multiple recording device support
-	BASS_RecordSetDevice
-	BASS_RecordGetDevice
-	BASS_RecordStart
-	BASS_ChannelGetDevice
-	HRECORD handle
-	RECORDPROC (handle parameter)
-* Recording with DSP/FX
-	BASS_ChannelSetDSP
-	BASS_ChannelSetFX
-* Recording position retrieval
-	BASS_ChannelGetPosition
-* Start recording paused
-	BASS_RECORD_PAUSE (BASS_RecordStart flag)
-* Multi-channel streams, inc. support for multichannel OGG & WAV files
-	BASS_StreamCreate
-	BASS_StreamCreateFile/User/URL
-* FFT for individual channels, inc. multi-channel streams
-	BASS_DATA_FFT_INDIVIDUAL (BASS_ChannelGetData flag)
-	BASS_DATA_FFT512S/1024S/2048S/4096S *removed*
-* DSP prioritizing
-	BASS_ChannelSetDSP
-	DSPTEST example updated
-* Seeking in internet streamed files
-	BASS_ChannelSetPosition
-* Enhanced custom file stream systems
-	BASS_StreamCreateFileUser
-	BASS_FILE_SEEK (STREAMFILEPROC action)
-	BASS_STREAM_FILEPROC flag *removed*
-* Enhanced custom stream system with automatic stalling/resuming
-	STREAMPROC
-	BASS_STREAMPROC_END (STREAMPROC flag)
-* Synchronizer for stalled/resumed playback 
-	BASS_SYNC_STALL (BASS_ChannelSetSync type)
-* Synchronizer for completed download
-	BASS_SYNC_DOWNLOAD (BASS_ChannelSetSync type)
-* End sync support for custom streams
-	BASS_SYNC_END (BASS_ChannelSetSync type)
-* Synchronizer support for decoding channels
-	BASS_ChannelSetSync
-* Unified configuration function
-	BASS_SetConfig
-	BASS_GetConfig
-	BASS_SetBufferLength *removed*
-	BASS_SetNetConfig *removed*
-	BASS_SetGlobalVolumes *removed*
-	BASS_GetGlobalVolumes *removed*
-	BASS_SetLogCurves *removed*
-	BASS_Set3DAlgorithm *removed*
-	BASS_DEVICE_FLOATDSP flag *removed*
-* Internet stream saving to disk replaced by more flexible callback
-	BASS_StreamCreateURL
-	DOWNLOADPROC
-	VB NETRADIO example updated
-* Buffer length retrieval when "streaming in blocks"
-	BASS_FILEPOS_END (BASS_StreamGetFilePosition mode)
-* Individual sample rate setting for MOD musics
-	BASS_MusicLoad
-* Channel type and default sample rate retrieval
-	BASS_ChannelGetInfo (replaces BASS_ChannelGetFlags)
-	BASS_CHANNELINFO
-* MOD music flag retrieval
-	BASS_CHANNELINFO (flags member)
-* Adjustable instrument volumes in MOD musics
-	BASS_MusicSetVolume (replaces BASS_MusicSetChannelVol)
-	BASS_MusicGetVolume (replaces BASS_MusicGetChannelVol)
-* Automatically free a MOD music when it stops or ends
-	BASS_MUSIC_AUTOFREE (BASS_MusicLoad flag)
-* Class GUID added to initialization parameters
-	BASS_Init
-	BASS_SetCLSID *removed*
-* Update period adjustable at any time
-	BASS_CONFIG_UPDATEPERIOD (BASS_SetConfig option)
-	BASS_DEVICE_NOTHREAD flag *removed*
-* Customizable maximum volume setting
-	BASS_CONFIG_MAXVOL (BASS_SetConfig option)
-	BASS_DEVICE_VOL1000 flag *removed*
-* Device volume is now always left as it is during init/freeing
-	BASS_DEVICE_LEAVEVOL flag *removed*
-* Device driver name retrieval
-	BASS_INFO (driver member)
-	BASS_RECORDINFO (driver member)
-* Error codes are local to the current thread
-	BASS_ErrorGetCode
-* Performance improvements
-	MP2 decoding 15-20% faster
-	MP3 decoding ~5% faster
-* Built-in CD functions removed (replaced in BASSCD)
-	BASS_CDDoor *removed*
-	BASS_CDFree *removed*
-	BASS_CDGetID *removed*
-	BASS_CDGetTrackLength *removed*
-	BASS_CDGetTracks *removed*
-	BASS_CDInDrive *removed*
-	BASS_CDInit *removed*
-	BASS_CDPlay *removed*
-* Force channels to use software mixing
-	BASS_SAMPLE_SOFTWARE (BASS_StreamCreate/File/User/URL & BASS_MusicLoad flag)
-* Support for high-pass filter and forward/reverse (S9E/F) IT/MPT effects
-* BASS_MUSIC flags rearranged to mirror BASS_SAMPLE/STREAM counterparts
-* Output automatically started during initialization
-* BASS_ChannelGetData once again accepts any "length" param
-* All function comments have been removed from the API headers to avoid
-  outdated/incorrect information - the documentation should be used.
-* TMT Pascal API removed from main distribution - now available on the website
-* A few more 'K' knocked off the DLL size :)
-
-1.8a - 18/6/2003
-----------------
-* Tweaks 'n' fixes, including...
-	Fixed seeking bug on 32-bit OGG streams
-	Fixed seeking on a decoding channel after it has reached the end
-	Low FPU precision (eg. when using Direct3D) issue addressed
-	Improved speakers (BASS_INFO) detection
-	BASS_ChannelSeconds2Bytes return value is rounded down to nearest sample
-	BASS_ChannelGetData "length" param must equal a whole number of samples
-	Slide syncs are triggered by "-2" volume slides on "autofree" streams
-* Support for Unicode filenames
-	BASS_UNICODE (BASS_SampleLoad/BASS_StreamCreateFile/BASS_MusicLoad flag)
-* 4096 sample FFT
-	BASS_DATA_FFT4096/S (BASS_ChannelGetData flags)
-* Another 'K' knocked off the DLL size
-
-1.8 - 9/3/2003
---------------
-* 32-bit floating-point channels
-	BASS_SAMPLE_FLOAT (BASS_StreamCreate/File/URL flag)
-	BASS_MUSIC_FLOAT (BASS_MusicLoad flag)
-	BASS_SAMPLE_FLOAT (BASS_RecordStart flag)
-	BASS_DEVICE_FLOATDSP (BASS_Init flag)
-	DSPTEST example updated
-* Support for 32-bit floating-point (type 3) WAV files
-	BASS_StreamCreateFile/URL
-	BASS_SampleLoad
-* Channel speaker assignment
-	BASS_SPEAKER_FRONT (BASS_MusicLoad/BASS_StreamCreate/File/URL flag)
-	BASS_SPEAKER_REAR                       "
-	BASS_SPEAKER_CENLFE                     "
-	BASS_SPEAKER_REAR2                      "
-	BASS_SPEAKER_FRONTLEFT                  "
-	BASS_SPEAKER_FRONTRIGHT                 "
-	BASS_SPEAKER_REARLEFT                   "
-	BASS_SPEAKER_REARRIGHT                  "
-	BASS_SPEAKER_CENTER                     "
-	BASS_SPEAKER_LFE                        "
-	BASS_SPEAKER_REAR2LEFT                  "
-	BASS_SPEAKER_REAR2RIGHT                 "
-	BASS_INFO (speakers member)
-	BASS_DEVICE_SPEAKERS (BASS_Init flag)
-	4SPEAKER example replaced by SPEAKERS example
-* Recording input type retrieval
-	BASS_INPUT_TYPE_xxx (BASS_RecordGetInput)
-	RECTEST example updated
-* Non-interpolated MOD mixing
-	BASS_MUSIC_NONINTER (BASS_MusicLoad/PlayEx flag)
-* Performance improvements
-	FFT up to 100% faster!
-	MP3(MPEG2/2.5) decoding up to 60% faster
-	MMX mixers 5-10% faster
-	MP3(MPEG1)/MP2/MP1/OGG decoding all ~5% faster
-* Optional disabling of FFT windowing
-	BASS_DATA_FFT_NOWINDOW (BASS_ChannelGetData flag)
-* BASS_ERROR_FILEFORM - error code to distinguish between file and sample format
-	BASS_MusicLoad
-	BASS_SampleLoad
-	BASS_StreamCreate/File/URL
-* BASS_StreamGetFilePosition mode flags added
-	BASS_FILEPOS_DECODE/DOWNLOAD/END
-* DirectSound 9 detection
-	BASS_INFO (dsver member)
-* Initialization flags retrieval
-	BASS_INFO (initflags member)
-* Half-rate MP3 playback option removed
-	BASS_MP3_HALFRATE flag *removed*
-* New internal "plugin" system - BASSWMA is further integrated as a result
-* Improved documentation - integrated with BASSWMA, search option added
-* VB version of DSPTEST example added
-* Delphi RECORDTEST example added
-* Guess what... reduced DLL size again :)
-
-1.7 - 27/10/2002
-----------------
-* New alternative DX8 (DMO) effects implementation
-	BASS_StreamCreate/File/URL
-	BASS_MusicLoad
-	BASS_ChannelSetFX
-	SYNTH example updated
-* User file streaming
-	BASS_STREAM_FILEPROC (BASS_StreamCreate flag)
-	STREAMFILEPROC
-* DSP & FX support for decoding channels
-	BASS_ChannelSetDSP
-	BASS_ChannelSetFX
-* Support for DX8 (DMO) effects in IT/XM/MO3 files
-	BASS_MusicLoad
-* Support for chained OGG streaming (and syncing)
-	BASS_StreamCreateURL
-	BASS_SYNC_META (BASS_ChannelSetSync type)
-* Attribute (volume/frequency/pan) sliding
-	BASS_ChannelSlideAttributes
-	BASS_ChannelIsSliding
-	BASS_SYNC_SLIDE (BASS_ChannelSetSync type)
-* Recording without a callback function
-	BASS_RecordStart
-	LIVEFX example added
-* Query a channel's buffered data
-	BASS_DATA_AVAILABLE (BASS_ChannelGetData flag)
-* Discard data from the recording buffer
-	BASS_ChannelGetData
-* Adjustable internet stream config (timeout/buffer lengths)
-	BASS_SetNetConfig
-* Recommended minimum buffer length
-	BASS_INFO (minbuf member)
-* MOD music flags adjustment without changing playback position
-	BASS_MusicPlayEx
-	PLAYER (MASM) example updated
-* More functions are now useable in MOD music "mixtime" syncs
-	SYNCPROC
-	BASS_ChannelSetPosition
-	BASS_MusicPlayEx
-	BASS_MusicSetAmplify
-	BASS_MusicSetPanSep
-* Maximum buffer length increased to 5 seconds
-	BASS_SetBufferLength
-* Support for extended filter range in IT files
-	BASS_MusicLoad
-* Speedier MOD music file verification
-	BASS_MusicLoad
-* Delphi 3DTEST example fixed
-* Magically reduced DLL size again :)
-
-1.6a - 25/8/2002
-----------------
-* OGG support updated to 1.0
-* Stereo FFT
-	BASS_DATA_FFT512S/1024S/2048S (BASS_ChannelGetData flags)
-* Support for "Invert Loop" (EFx) MOD effect
-* Reduced DLL size
-* New Delphi examples
-	WRITEWAV - WAVE writer example
-	SAMPLEVIS - Visualisation example
-
-1.6 - 13/6/2002
----------------
-* 64-bit stream lengths and positions
-	BASS_StreamGetLength
-	BASS_ChannelBytes2Seconds
-	BASS_ChannelSeconds2Bytes
-	BASS_ChannelGetPosition
-	BASS_ChannelSetPosition
-	BASS_ChannelSetSync
-* Recording input selection
-	BASS_RECORDINFO (inputs & singlein members)
-	BASS_RecordGetInputName
-	BASS_RecordGetInput
-	BASS_RecordSetInput
-* Adjustable recording update period
-	BASS_RecordStart
-* Load OGG files as samples
-	BASS_SampleLoad
-* CD drive door opening & closing
-	BASS_CDDoor
-* CDDB2 ID retrieval
-	BASS_CDID_CDDB2 (BASS_CDGetID flag)
-* Streaming beyond initial file length
-	BASS_StreamCreateFile
-* Recording position bytes<->seconds translation
-	BASS_ChannelBytes2Seconds
-	BASS_ChannelSeconds2Bytes
-* Improved multi-threaded support (play from any thread)
-	BASS_MusicPlay/Ex
-	BASS_SamplePlay/3D/Ex
-	BASS_StreamPlay
-	BASS_DEVICE_NOSYNC flag *removed*
-* Paused channel status
-	BASS_ACTIVE_PAUSED (BASS_ChannelIsActive)
-* Integrated WMA stream freeing
-	BASS_StreamFree
-	BASS_Free
-* Pin-point accurate OGG seeking without BASS_MP3_SETPOS flag
-* Win2k DS buffer bug fix
-
-1.5a - 14/4/2002
-----------------
-* NT4 fix (also enables "nosound" device without DX installed)
-	BASS_ERROR_DX error code
-* MOD music loading without the samples
-	BASS_MUSIC_NOSAMPLE (BASS_MusicLoad flag)
-* Custom decoding channels
-	BASS_STREAM_DECODE (BASS_StreamCreate flag)
-* 5 second HTTP connection timeout
-	BASS_ERROR_TIMEOUT (BASS_StreamCreateURL error code)
-
-1.5 - 31/3/2002
----------------
-* Improved performance
-	MMX mixers lot faster (over 50% faster in some cases!)
-	OGG decoding 15-20% faster
-	MP3 decoding 5-10% faster
-* Recording
-	BASS_RecordGetDeviceDescription
-	BASS_RecordInit
-	BASS_RecordFree
-	BASS_RecordGetInfo
-	BASS_RecordStart
-* OGG support built-in (OGG/VORBIS DLLs not required)
-	BASS_DEVICE_OGG flag *removed*
-* MOD music seeking in seconds
-	BASS_MusicPlayEx
-	BASS_ChannelSetPosition
-* Shoutcast metadata retrieval
-	BASS_STREAM_META (BASS_StreamCreateURL flag)
-	BASS_TAG_META (BASS_StreamGetTags type)
-	BASS_SYNC_META (BASS_ChannelSetSync type)
-* 1000 volume levels
-	BASS_DEVICE_VOL1000 (BASS_Init/CDInit flag)
-* CDDB ID retrieval
-	BASS_CDID_CDDB (BASS_CDGetID flag)
-* Leave the CD volume as it is during init/closing
-	BASS_DEVICE_LEAVEVOL (BASS_CDInit flag)
-* FFT enabled on decoding channels
-	BASS_ChannelGetData
-* Left level duplicated on right for mono channels
-	BASS_ChannelGetLevel
-* Improved MPEG length estimation without BASS_MP3_SETPOS flag
-	BASS_StreamGetLength
-* Support for Modplug/ADPCM compressed files
-	BASS_MusicLoad
-* Device description function parameter change
-	BASS_GetDeviceDescription
-* MASM API
-
-1.4 - 30/1/2002
----------------
-* Channel decoding without playback
-	BASS_MUSIC_DECODE (BASS_MusicLoad flag)
-	BASS_STREAM_DECODE (BASS_StreamCreateFile/URL flag)
-	BASS_ChannelGetData
-* Windows message sync callbacks
-	BASS_SYNC_MESSAGE (BASS_ChannelSetSync flag)
-* Adjustable channel volumes in MOD musics
-	BASS_MusicSetChannelVol
-	BASS_MusicGetChannelVol
-* Customizable DirectSound initialization object
-	BASS_SetCLSID
-* Retrieve HMUSIC/HSTREAM/HCHANNEL IDirectSoundBuffer interfaces
-	BASS_GetDSoundObject
-* A3D functions removed (use BASS_SetCLSID/BASS_GetDSoundObject to access A3D)
-	BASS_DEVICE_A3D (BASS_Init flag)
-	BASS_SetA3DResManager
-	BASS_GetA3DResManager
-	BASS_SetA3DHFAbsorbtion
-	BASS_GetA3DHFAbsorbtion
-* Callback functions now work in VB6
-	DSPPROC
-	STREAMPROC
-	SYNCPROC
-* Improved PCM WAVE streaming performance
-	BASS_StreamCreateFile
-	BASS_StreamCreateURL
-* OGG modules updated to RC3
-* Stereo sample support in MO3 format
-* MO3 encoder now distributed separately from BASS
-
-1.3 - 17/11/2001
-----------------
-* Manual buffer updating
-	BASS_DEVICE_NOTHREAD (BASS_Init flag)
-	BASS_Update
-* Adjustable buffer update period (allows small buffer sizes)
-	BASS_Init
-* Output device latency retrieval
-	BASS_INFO (latency member)
-* MPEG/OGG seeking without BASS_MP3_SETPOS flag
-	BASS_ChannelSetPosition
-* Internet file streaming from offsets
-	BASS_StreamCreateURL
-* File stream tag/comment retrieval (ID3/ID3v2/OGG/HTTP/ICY tags)
-	BASS_StreamGetTags
-* Byte<->time position translation
-	BASS_ChannelBytes2Seconds
-	BASS_ChannelSeconds2Bytes
-* UMX (Unreal/Tournament music package) format support
-	BASS_MusicLoad
-* S3M/IT sync fx changed to S2x (S0x conflicted with S00)
-	BASS_SYNC_MUSICFX
-* Stereo sample support in IT/XM/S3M formats
-* MO3: OGG compression supported
-
-1.2 - 25/9/2001
----------------
-* OGG (Ogg Vorbis) stream support
-	BASS_DEVICE_OGG (BASS_Init flag)
-	BASS_StreamCreateFile
-	BASS_StreamCreateURL
-* Channel linking (start/stop/pause/resume channels together)
-	BASS_ChannelSetLink
-	BASS_ChannelRemoveLink
-* MOD music playback length calculation
-	BASS_MUSIC_CALCLEN (BASS_MusicLoad flag)
-	BASS_MusicGetLength
-* Pre-buffering
-	BASS_MusicPreBuf
-	BASS_StreamPreBuf
-* Samples with single simultaneous playbacks have same HSAMPLE/HCHANNEL handle
-	BASS_SamplePlay/Ex
-* Stopping a custom stream flushes its buffer contents
-	BASS_ChannelStop
-
-1.1a - 31/8/2001
-----------------
-* NT4 bug fixed
-* XM Wxx effect syncing
-	BASS_SYNC_MUSICFX
-* MP3/2/1 rewinding without BASS_MP3_SETPOS
-	BASS_ChannelSetPosition
-
-1.1 - 11/8/2001
----------------
-* DX8 (DMO) effects
-	BASS_SAMPLE_FX (BASS_StreamCreate/File/URL flag)
-	BASS_MUSIC_FX (BASS_MusicLoad flag)
-	BASS_ChannelSetFX
-	BASS_ChannelRemoveFX
-	BASS_FXSetParameters
-	BASS_FXGetParameters
-	BASS_FXCHORUS structure
-	BASS_FXCOMPRESSOR structure
-	BASS_FXDISTORTION structure
-	BASS_FXECHO structure
-	BASS_FXFLANGER structure
-	BASS_FXGARGLE structure
-	BASS_FXI3DL2REVERB structure
-	BASS_FXPARAMEQ structure
-	BASS_FXREVERB structure
-* Internet file streaming in blocks (inc. Shoutcast/Icecast stream support)
-	BASS_STREAM_BLOCK (BASS_StreamCreateURL flag)
-* 512/1024/2048 sample FFT
-	BASS_DATA_FFT512/1024/2048 (BASS_ChannelGetData flags)
-* CD identification
-	BASS_CDGetID
-* Improved DX version detection
-	BASS_INFO (dsver member)
-
-1.0 - 20/6/2001
----------------
-* Load MP3/MP2/MP1 files as samples
-	BASS_SampleLoad
-* Internet file streaming from FTP servers
-	BASS_StreamCreateURL
-* Save a local copy of internet file streams
-	BASS_StreamCreateURL
-* Sample accurate file stream seeking
-	BASS_ChannelSetPosition
-	BASS_StreamGetBlockLength *removed*
-* Stream position synchronizer
-	BASS_SYNC_POS
-* Increased synchronizer precision
-* Improved MPEG file detection and error detection
-* Stop MOD musics on a backwards jump effect
-	BASS_MUSIC_STOPBACK (BASS_MusicLoad/PlayEx flag)
-* Leave the volume as it is during closing (as well as initialization)
-	BASS_DEVICE_LEAVEVOL (BASS_Init flag)
-* Optional automatic use of foreground window handle during initialization
-	BASS_Init
-* Reduced DLL size
-* VB API fixes
-
-0.9 - 18/4/2001
----------------
-* Internet file streaming
-	BASS_StreamCreateURL
-* MP1 & MP2 (MPEG layer 1 & 2) support
-	BASS_StreamCreateFile/URL
-* MPEG 2.5 support (12000/11025/8000hz sample rates)
-	BASS_StreamCreateFile/URL
-* Decoding/download/end file stream position retrieval
-	BASS_StreamGetFilePosition
-* XMPlay surround sound for MOD musics
-	BASS_MUSIC_SURROUND (BASS_MusicLoad/PlayEx flag)
-	BASS_MUSIC_SURROUND2 (BASS_MusicLoad/PlayEx flag)
-* Restrict the download rate of internet file streams
-	BASS_STREAM_RESTRATE (BASS_StreamCreateURL flag)
-* Check if an internet file stream is stalled
-	BASS_ChannelIsActive
-* Automatically free a stream when it stops or ends
-	BASS_STREAM_AUTOFREE (BASS_StreamCreate/File/URL flag)
-* Leave the volume as it is during initialization
-	BASS_DEVICE_LEAVEVOL (BASS_Init flag)
-* Number of CD tracks retrieval
-	BASS_CDGetTracks
-* CD track length retrieval
-	BASS_CDGetTrackLength
-* Exact stream length set after whole file is streamed
-	BASS_StreamGetLength
-* TMT Pascal API and samples
-* Dynamic-loading Delphi API
-
-0.8a - 28/2/2000
-----------------
-* Updated Delphi API and samples
-
-0.8 - 24/1/2000
----------------
-* Improved MP3 performance on P2/K6 and above CPUs
-* User DSP functions on streams and MOD musics
-	BASS_ChannelSetDSP
-	BASS_ChannelRemoveDSP
-* DX7 voice allocation & management
-	BASS_SAMPLE_VAM (BASS_SampleLoad/Create flag)
-	BASS_VAM_xxx flags
-	BASS_SAMPLE (vam & priority members)
-* DX7 software 3D algorithm selection
-	BASS_Set3DAlgorithm
-* DirectSound interface retrieval
-	BASS_GetDSoundObject
-* Log/linear volume & panning curves
-	BASS_SetLogCurves
-* User data passed to callback functions
-	STREAMPROC - BASS_StreamCreate
-	SYNCPROC - BASS_ChannelSetSync
-* New synchronizer
-	BASS_SYNC_MUSICFX
-* New synchronizer flag
-	BASS_SYNC_MIXTIME
-* Disable synchronizers option - saves a little CPU time
-	BASS_DEVICE_NOSYNC (BASS_Init flag)
-* Hi-res floating-point CPU usage monitoring
-	BASS_GetCPU
-* Wait for playback to start when playing a CD
-	BASS_CDPlay
-* DirectSound (dsound.dll) version retrieval
-	BASS_INFO (dsver member)
-* Removed volume sliding functions (they were fairly pointless)
-	BASS_SlideVolume
-	BASS_IsSliding
-* MO3: read/write encoder settings
-* MO3: remove inst/samp/message texts now optional
-* MO3: LAME encoder settings
-
-0.7 - 3/10/1999
----------------
-* MO3 (MP3 compressed MODs)
-* A3D functions
-	BASS_DEVICE_A3D (BASS_Init flag)
-	BASS_INFO (a3d member)
-	BASS_SetA3DResManager
-	BASS_GetA3DResManager
-	BASS_SetA3DHFAbsorbtion
-	BASS_GetA3DHFAbsorbtion
-* Music/stream immediate sample data retrieval
-	BASS_ChannelGetData
-* File stream (WAV/MP3) length retrieval
-	BASS_StreamGetLength
-	BASS_StreamGetBlockLength
-* File stream seeking
-	BASS_ChannelSetPosition
-* Mono MP3 option (lower CPU usage)
-	BASS_StreamCreateFile
-* Music length retrieval
-	BASS_MusicGetLength
-* Music name retrieval
-	BASS_MusicGetName
-* Stop notes when moving MOD music position
-	BASS_MUSIC_POSRESET (BASS_MusicLoad/BASS_MusicPlayEx flag)
-* BASS_ERROR_FREQ - invalid sample rate error code
-	BASS_SampleCreate
-	BASS_SamplePlayEx
-	BASS_SamplePlay3DEx
-	BASS_StreamCreate
-	BASS_ChannelSetAttributes
-* Delphi and VB APIs
-
-0.6a - 26/7/1999
-----------------
-* Half rate MP3 option (lower CPU usage)
-	BASS_MP3_HALFRATE
-* Loading/streaming from file offsets
-	BASS_MusicLoad
-	BASS_SampleLoad
-	BASS_StreamCreateFile
-* Global music/sample/stream volume levels
-	BASS_SetGlobalVolumes
-	BASS_GetGlobalVolumes
-* Other new function
-	BASS_SampleStop
-* New synchronizer
-	BASS_SYNC_END
-* New sample overrider
-	BASS_SAMPLE_OVER_DIST
-* LoadLibrary/GetProcAddress instructions and example
-
-0.5 - 4/7/1999
---------------
-* Documentation!
-* File streaming (MP3 and WAV)
-	BASS_StreamCreateFile
-* Custom generated samples
-	BASS_SampleCreate
-	BASS_SampleCreateDone
-* Other new function
-	BASS_MusicSetPositionScaler
-* Renamed function
-	BASS_ChannelClearSync -> BASS_ChannelRemoveSync
-* Alterations made to
-	BASS_ChannelGetPosition
-	BASS_SampleLoad
-	BASS_StreamPlay
-
-0.4 - 30/3/1999
----------------
-* Compressed WAV samples support (using audio CODECs)
-* Updated CD volume handling - now works with SB Live
-* More linear channel volume/pan scales (were slightly off before)
-* "No sound" device option
-* 3D sound functions
-	BASS_Set3DFactors
-	BASS_Get3DFactors
-	BASS_Set3DPosition
-	BASS_Get3DPosition
-	BASS_Apply3D
-	BASS_SamplePlay3D
-	BASS_SamplePlay3DEx
-	BASS_ChannelSet3DAttributes
-	BASS_ChannelGet3DAttributes
-	BASS_ChannelSet3DPosition
-	BASS_ChannelGet3DPosition
-* EAX functions
-	BASS_SetEAXParameters
-	BASS_GetEAXParameters
-	BASS_ChannelSetEAXMix
-	BASS_ChannelGetEAXMix
-* Other new functions
-	BASS_GetDeviceDescription
-	BASS_SetBufferLen
-	BASS_ChannelGetFlags
-	BASS_ChannelPause
-	BASS_ChannelResume
-	BASS_ChannelSetPosition
-* Replaced function
-	BASS_CDResume -> BASS_ChannelResume
-* Alterations made to
-	BASS_Init
-	BASS_CDInit
-	BASS_SampleLoad
-	BASS_StreamPlay
-	BASS_INFO structure
-	BASS_SAMPLE structure
-	BASS_DEVICE_xxx flags
-	BASS_SAMPLE_xxx flags
-
-0.3 - 8/3/1999
---------------
-* Synchronization functions
-	BASS_ChannelSetSync
-	BASS_ChannelClearSync
-* Other new functions
-	BASS_GetVersion
-	BASS_ChannelGetPosition
-	BASS_ChannelGetLevel
-	BASS_ChannelGetAttributes
-	BASS_ChannelSetAttributes
-* Replaced functions
-	BASS_MusicStop -> BASS_ChannelStop
-	BASS_MusicSetVolume -> BASS_ChannelSetAttributes
-	BASS_CDStop -> BASS_ChannelStop
-	BASS_CDSetVolume -> BASS_ChannelSetAttributes
-	BASS_CDGetVolume -> BASS_ChannelGetAttributes
-	BASS_ChannelUpdate -> BASS_ChannelSetAttributes
-* Alterations made to
-	BASS_MusicPlayEx
-	BASS_StreamPlay
-	BASS_INFO structure
-
-0.2 - 28/2/1999
----------------
-* First public release
-
-
-Bug reports, Suggestions, Comments, Enquiries, etc
-==================================================
-If you have any of the aforementioned please visit the BASS forum at the
-website. If you can't find an answer there, you can also email:
-
-	bass@un4seen.com
-

+ 0 - 43
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bass.xcframework/Info.plist

@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>AvailableLibraries</key>
-	<array>
-		<dict>
-			<key>LibraryIdentifier</key>
-			<string>ios-arm64_armv7_armv7s</string>
-			<key>LibraryPath</key>
-			<string>libbass.a</string>
-			<key>SupportedArchitectures</key>
-			<array>
-				<string>arm64</string>
-				<string>armv7</string>
-				<string>armv7s</string>
-			</array>
-			<key>SupportedPlatform</key>
-			<string>ios</string>
-		</dict>
-		<dict>
-			<key>LibraryIdentifier</key>
-			<string>ios-arm64_i386_x86_64-simulator</string>
-			<key>LibraryPath</key>
-			<string>libbass.a</string>
-			<key>SupportedArchitectures</key>
-			<array>
-				<string>arm64</string>
-				<string>i386</string>
-				<string>x86_64</string>
-			</array>
-			<key>SupportedPlatform</key>
-			<string>ios</string>
-			<key>SupportedPlatformVariant</key>
-			<string>simulator</string>
-		</dict>
-	</array>
-	<key>CFBundlePackageType</key>
-	<string>XFWK</string>
-	<key>XCFrameworkFormatVersion</key>
-	<string>1.0</string>
-</dict>
-</plist>

BIN
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bass.xcframework/ios-arm64_armv7_armv7s/libbass.a


BIN
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bass.xcframework/ios-arm64_i386_x86_64-simulator/libbass.a


+ 0 - 424
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bassmidi.h

@@ -1,424 +0,0 @@
-/*
-	BASSMIDI 2.4 C/C++ header file
-	Copyright (c) 2006-2022 Un4seen Developments Ltd.
-
-	See the BASSMIDI.CHM file for more detailed documentation
-*/
-
-#ifndef BASSMIDI_H
-#define BASSMIDI_H
-
-#include "bass.h"
-
-#if BASSVERSION!=0x204
-#error conflicting BASS and BASSMIDI versions
-#endif
-
-#ifdef __OBJC__
-typedef int BOOL32;
-#define BOOL BOOL32 // override objc's BOOL
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef BASSMIDIDEF
-#define BASSMIDIDEF(f) WINAPI f
-#endif
-
-typedef DWORD HSOUNDFONT;	// soundfont handle
-
-// Additional error codes returned by BASS_ErrorGetCode
-#define BASS_ERROR_MIDI_INCLUDE		7000	// SFZ include file could not be opened
-
-// Additional BASS_SetConfig options
-#define BASS_CONFIG_MIDI_COMPACT	0x10400
-#define BASS_CONFIG_MIDI_VOICES		0x10401
-#define BASS_CONFIG_MIDI_AUTOFONT	0x10402
-#define BASS_CONFIG_MIDI_IN_PORTS	0x10404
-#define BASS_CONFIG_MIDI_SAMPLETHREADS 0x10406
-#define BASS_CONFIG_MIDI_SAMPLEMEM	0x10407
-#define BASS_CONFIG_MIDI_SAMPLEREAD	0x10408
-#define BASS_CONFIG_MIDI_SAMPLELOADING	0x1040a
-
-// Additional BASS_SetConfigPtr options
-#define BASS_CONFIG_MIDI_DEFFONT	0x10403
-#define BASS_CONFIG_MIDI_SFZHEAD	0x10409
-
-// Additional sync types
-#define BASS_SYNC_MIDI_MARK		0x10000
-#define BASS_SYNC_MIDI_MARKER	0x10000
-#define BASS_SYNC_MIDI_CUE		0x10001
-#define BASS_SYNC_MIDI_LYRIC	0x10002
-#define BASS_SYNC_MIDI_TEXT		0x10003
-#define BASS_SYNC_MIDI_EVENT	0x10004
-#define BASS_SYNC_MIDI_TICK		0x10005
-#define BASS_SYNC_MIDI_TIMESIG	0x10006
-#define BASS_SYNC_MIDI_KEYSIG	0x10007
-
-// Additional BASS_MIDI_StreamCreateFile/etc flags
-#define BASS_MIDI_NODRUMPARAM	0x400
-#define BASS_MIDI_NOSYSRESET	0x800
-#define BASS_MIDI_DECAYEND		0x1000
-#define BASS_MIDI_NOFX			0x2000
-#define BASS_MIDI_DECAYSEEK		0x4000
-#define BASS_MIDI_NOCROP		0x8000
-#define BASS_MIDI_NOTEOFF1		0x10000
-#define BASS_MIDI_ASYNC			0x400000
-#define BASS_MIDI_SINCINTER		0x800000
-
-// BASS_MIDI_FontInit flags
-#define BASS_MIDI_FONT_MEM		0x10000
-#define BASS_MIDI_FONT_MMAP		0x20000
-#define BASS_MIDI_FONT_XGDRUMS	0x40000
-#define BASS_MIDI_FONT_NOFX		0x80000
-#define BASS_MIDI_FONT_LINATTMOD	0x100000
-#define BASS_MIDI_FONT_LINDECVOL	0x200000
-#define BASS_MIDI_FONT_NORAMPIN		0x400000
-#define BASS_MIDI_FONT_NOLIMITS		0x800000
-#define BASS_MIDI_FONT_MINFX		0x1000000
-
-typedef struct {
-	HSOUNDFONT font;	// soundfont
-	int preset;			// preset number (-1=all)
-	int bank;
-} BASS_MIDI_FONT;
-
-typedef struct {
-	HSOUNDFONT font;	// soundfont
-	int spreset;		// source preset number
-	int sbank;			// source bank number
-	int dpreset;		// destination preset/program number
-	int dbank;			// destination bank number
-	int dbanklsb;		// destination bank number LSB
-} BASS_MIDI_FONTEX;
-
-typedef struct {
-	HSOUNDFONT font;	// soundfont
-	int spreset;		// source preset number
-	int sbank;			// source bank number
-	int dpreset;		// destination preset/program number
-	int dbank;			// destination bank number
-	int dbanklsb;		// destination bank number LSB
-	DWORD minchan;		// minimum channel number
-	DWORD numchan;		// number of channels from minchan
-} BASS_MIDI_FONTEX2;
-
-// BASS_MIDI_StreamSet/GetFonts flag
-#define BASS_MIDI_FONT_EX		0x1000000	// BASS_MIDI_FONTEX
-#define BASS_MIDI_FONT_EX2		0x2000000	// BASS_MIDI_FONTEX2
-
-typedef struct {
-	const char *name;
-	const char *copyright;
-	const char *comment;
-	DWORD presets;		// number of presets/instruments
-	DWORD samsize;		// total size (in bytes) of the sample data
-	DWORD samload;		// amount of sample data currently loaded
-	DWORD samtype;		// sample format (CTYPE) if packed
-} BASS_MIDI_FONTINFO;
-
-typedef struct {
-	DWORD track;		// track containing marker
-	DWORD pos;			// marker position
-	const char *text;	// marker text
-} BASS_MIDI_MARK;
-
-// Marker types
-#define BASS_MIDI_MARK_MARKER	0	// marker
-#define BASS_MIDI_MARK_CUE		1	// cue point
-#define BASS_MIDI_MARK_LYRIC	2	// lyric
-#define BASS_MIDI_MARK_TEXT		3	// text
-#define BASS_MIDI_MARK_TIMESIG	4	// time signature
-#define BASS_MIDI_MARK_KEYSIG	5	// key signature
-#define BASS_MIDI_MARK_COPY		6	// copyright notice
-#define BASS_MIDI_MARK_TRACK	7	// track name
-#define BASS_MIDI_MARK_INST		8	// instrument name
-#define BASS_MIDI_MARK_TRACKSTART	9	// track start (SMF2)
-#define BASS_MIDI_MARK_TICK		0x10000 // flag: get position in ticks (otherwise bytes)
-
-// MIDI events
-#define MIDI_EVENT_NOTE				1
-#define MIDI_EVENT_PROGRAM			2
-#define MIDI_EVENT_CHANPRES			3
-#define MIDI_EVENT_PITCH			4
-#define MIDI_EVENT_PITCHRANGE		5
-#define MIDI_EVENT_DRUMS			6
-#define MIDI_EVENT_FINETUNE			7
-#define MIDI_EVENT_COARSETUNE		8
-#define MIDI_EVENT_MASTERVOL		9
-#define MIDI_EVENT_BANK				10
-#define MIDI_EVENT_MODULATION		11
-#define MIDI_EVENT_VOLUME			12
-#define MIDI_EVENT_PAN				13
-#define MIDI_EVENT_EXPRESSION		14
-#define MIDI_EVENT_SUSTAIN			15
-#define MIDI_EVENT_SOUNDOFF			16
-#define MIDI_EVENT_RESET			17
-#define MIDI_EVENT_NOTESOFF			18
-#define MIDI_EVENT_PORTAMENTO		19
-#define MIDI_EVENT_PORTATIME		20
-#define MIDI_EVENT_PORTANOTE		21
-#define MIDI_EVENT_MODE				22
-#define MIDI_EVENT_REVERB			23
-#define MIDI_EVENT_CHORUS			24
-#define MIDI_EVENT_CUTOFF			25
-#define MIDI_EVENT_RESONANCE		26
-#define MIDI_EVENT_RELEASE			27
-#define MIDI_EVENT_ATTACK			28
-#define MIDI_EVENT_DECAY			29
-#define MIDI_EVENT_REVERB_MACRO		30
-#define MIDI_EVENT_CHORUS_MACRO		31
-#define MIDI_EVENT_REVERB_TIME		32
-#define MIDI_EVENT_REVERB_DELAY		33
-#define MIDI_EVENT_REVERB_LOCUTOFF	34
-#define MIDI_EVENT_REVERB_HICUTOFF	35
-#define MIDI_EVENT_REVERB_LEVEL		36
-#define MIDI_EVENT_CHORUS_DELAY		37
-#define MIDI_EVENT_CHORUS_DEPTH		38
-#define MIDI_EVENT_CHORUS_RATE		39
-#define MIDI_EVENT_CHORUS_FEEDBACK	40
-#define MIDI_EVENT_CHORUS_LEVEL		41
-#define MIDI_EVENT_CHORUS_REVERB	42
-#define MIDI_EVENT_USERFX			43
-#define MIDI_EVENT_USERFX_LEVEL		44
-#define MIDI_EVENT_USERFX_REVERB	45
-#define MIDI_EVENT_USERFX_CHORUS	46
-#define MIDI_EVENT_DRUM_FINETUNE	50
-#define MIDI_EVENT_DRUM_COARSETUNE	51
-#define MIDI_EVENT_DRUM_PAN			52
-#define MIDI_EVENT_DRUM_REVERB		53
-#define MIDI_EVENT_DRUM_CHORUS		54
-#define MIDI_EVENT_DRUM_CUTOFF		55
-#define MIDI_EVENT_DRUM_RESONANCE	56
-#define MIDI_EVENT_DRUM_LEVEL		57
-#define MIDI_EVENT_DRUM_USERFX		58
-#define MIDI_EVENT_SOFT				60
-#define MIDI_EVENT_SYSTEM			61
-#define MIDI_EVENT_TEMPO			62
-#define MIDI_EVENT_SCALETUNING		63
-#define MIDI_EVENT_CONTROL			64
-#define MIDI_EVENT_CHANPRES_VIBRATO	65
-#define MIDI_EVENT_CHANPRES_PITCH	66
-#define MIDI_EVENT_CHANPRES_FILTER	67
-#define MIDI_EVENT_CHANPRES_VOLUME	68
-#define MIDI_EVENT_MOD_VIBRATO		69
-#define MIDI_EVENT_MODRANGE			69
-#define MIDI_EVENT_BANK_LSB			70
-#define MIDI_EVENT_KEYPRES			71
-#define MIDI_EVENT_KEYPRES_VIBRATO	72
-#define MIDI_EVENT_KEYPRES_PITCH	73
-#define MIDI_EVENT_KEYPRES_FILTER	74
-#define MIDI_EVENT_KEYPRES_VOLUME	75
-#define MIDI_EVENT_SOSTENUTO		76
-#define MIDI_EVENT_MOD_PITCH		77
-#define MIDI_EVENT_MOD_FILTER		78
-#define MIDI_EVENT_MOD_VOLUME		79
-#define MIDI_EVENT_VIBRATO_RATE		80
-#define MIDI_EVENT_VIBRATO_DEPTH	81
-#define MIDI_EVENT_VIBRATO_DELAY	82
-#define MIDI_EVENT_MASTER_FINETUNE	83
-#define MIDI_EVENT_MASTER_COARSETUNE	84
-#define MIDI_EVENT_MIXLEVEL			0x10000
-#define MIDI_EVENT_TRANSPOSE		0x10001
-#define MIDI_EVENT_SYSTEMEX			0x10002
-#define MIDI_EVENT_SPEED			0x10004
-#define MIDI_EVENT_DEFDRUMS			0x10006
-
-#define MIDI_EVENT_END				0
-#define MIDI_EVENT_END_TRACK		0x10003
-
-#define MIDI_EVENT_NOTES			0x20000
-#define MIDI_EVENT_VOICES			0x20001
-
-#define MIDI_SYSTEM_DEFAULT			0
-#define MIDI_SYSTEM_GM1				1
-#define MIDI_SYSTEM_GM2				2
-#define MIDI_SYSTEM_XG				3
-#define MIDI_SYSTEM_GS				4
-
-typedef struct {
-	DWORD event;		// MIDI_EVENT_xxx
-	DWORD param;
-	DWORD chan;
-	DWORD tick;			// event position (ticks)
-	DWORD pos;			// event position (bytes)
-} BASS_MIDI_EVENT;
-
-// BASS_MIDI_StreamEvents modes
-#define BASS_MIDI_EVENTS_STRUCT		0 // BASS_MIDI_EVENT structures
-#define BASS_MIDI_EVENTS_RAW		0x10000 // raw MIDI event data
-#define BASS_MIDI_EVENTS_SYNC		0x1000000 // flag: trigger event syncs
-#define BASS_MIDI_EVENTS_NORSTATUS	0x2000000 // flag: no running status
-#define BASS_MIDI_EVENTS_CANCEL		0x4000000 // flag: cancel pending events
-#define BASS_MIDI_EVENTS_TIME		0x8000000 // flag: delta-time info is present
-#define BASS_MIDI_EVENTS_ABSTIME	0x10000000 // flag: absolute time info is present
-#define BASS_MIDI_EVENTS_ASYNC		0x20000000 // flag: process asynchronously
-#define BASS_MIDI_EVENTS_FILTER		0x40000000 // flag: apply filtering
-#define BASS_MIDI_EVENTS_FLUSH		0x80000000 // flag: flush async events
-
-// BASS_MIDI_StreamGetChannel special channels
-#define BASS_MIDI_CHAN_CHORUS		(DWORD)-1
-#define BASS_MIDI_CHAN_REVERB		(DWORD)-2
-#define BASS_MIDI_CHAN_USERFX		(DWORD)-3
-
-// BASS_CHANNELINFO type
-#define BASS_CTYPE_STREAM_MIDI	0x10d00
-
-// Additional attributes
-#define BASS_ATTRIB_MIDI_PPQN		0x12000
-#define BASS_ATTRIB_MIDI_CPU		0x12001
-#define BASS_ATTRIB_MIDI_CHANS		0x12002
-#define BASS_ATTRIB_MIDI_VOICES		0x12003
-#define BASS_ATTRIB_MIDI_VOICES_ACTIVE 0x12004
-#define BASS_ATTRIB_MIDI_STATE		0x12005
-#define BASS_ATTRIB_MIDI_SRC		0x12006
-#define BASS_ATTRIB_MIDI_KILL		0x12007
-#define BASS_ATTRIB_MIDI_SPEED		0x12008
-#define BASS_ATTRIB_MIDI_REVERB		0x12009
-#define BASS_ATTRIB_MIDI_VOL		0x1200a
-#define BASS_ATTRIB_MIDI_TRACK_VOL	0x12100 // + track #
-
-// Additional tag type
-#define BASS_TAG_MIDI_TRACK	0x11000	// + track #, track text : array of null-terminated ANSI strings
-
-// BASS_ChannelGetLength/GetPosition/SetPosition mode
-#define BASS_POS_MIDI_TICK		2		// tick position
-
-typedef BOOL (CALLBACK MIDIFILTERPROC)(HSTREAM handle, int track, BASS_MIDI_EVENT *event, BOOL seeking, void *user);
-/* Event filtering callback function.
-handle : MIDI stream handle
-track  : Track containing the event
-event  : The event
-seeking: TRUE = the event is being processed while seeking, FALSE = it is being played
-user   : The 'user' parameter value given when calling BASS_MIDI_StreamSetFilter
-RETURN : TRUE = process the event, FALSE = drop the event */
-
-// BASS_MIDI_FontLoadEx flags
-#define BASS_MIDI_FONTLOAD_NOWAIT	1	// don't want for the samples to load
-#define BASS_MIDI_FONTLOAD_COMPACT	2	// compact samples
-#define BASS_MIDI_FONTLOAD_NOLOAD	4	// don't load (only compact)
-#define BASS_MIDI_FONTLOAD_TIME		8	// length is in milliseconds
-#define BASS_MIDI_FONTLOAD_KEEPDEC	16	// keep decoders
-
-// BASS_MIDI_FontPack flags
-#define BASS_MIDI_PACK_NOHEAD		1	// don't send a WAV header to the encoder
-#define BASS_MIDI_PACK_16BIT		2	// discard low 8 bits of 24-bit sample data
-#define BASS_MIDI_PACK_48KHZ		4	// set encoding rate to 48000 Hz (else 44100 Hz)
-
-typedef struct {
-	const char *name;	// description
-	DWORD id;
-	DWORD flags;
-} BASS_MIDI_DEVICEINFO;
-
-typedef void (CALLBACK MIDIINPROC)(DWORD device, double time, const BYTE *buffer, DWORD length, void *user);
-/* MIDI input callback function.
-device : MIDI input device
-time   : Timestamp
-buffer : Buffer containing MIDI data
-length : Number of bytes of data
-user   : The 'user' parameter value given when calling BASS_MIDI_InInit */
-
-DWORD BASSMIDIDEF(BASS_MIDI_GetVersion)(void);
-
-HSTREAM BASSMIDIDEF(BASS_MIDI_StreamCreate)(DWORD channels, DWORD flags, DWORD freq);
-HSTREAM BASSMIDIDEF(BASS_MIDI_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags, DWORD freq);
-HSTREAM BASSMIDIDEF(BASS_MIDI_StreamCreateURL)(const char *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user, DWORD freq);
-HSTREAM BASSMIDIDEF(BASS_MIDI_StreamCreateFileUser)(DWORD system, DWORD flags, const BASS_FILEPROCS *procs, void *user, DWORD freq);
-HSTREAM BASSMIDIDEF(BASS_MIDI_StreamCreateEvents)(const BASS_MIDI_EVENT *events, DWORD ppqn, DWORD flags, DWORD freq);
-BOOL BASSMIDIDEF(BASS_MIDI_StreamGetMark)(HSTREAM handle, DWORD type, DWORD index, BASS_MIDI_MARK *mark);
-DWORD BASSMIDIDEF(BASS_MIDI_StreamGetMarks)(HSTREAM handle, int track, DWORD type, BASS_MIDI_MARK *marks);
-BOOL BASSMIDIDEF(BASS_MIDI_StreamSetFonts)(HSTREAM handle, const void *fonts, DWORD count);
-DWORD BASSMIDIDEF(BASS_MIDI_StreamGetFonts)(HSTREAM handle, void *fonts, DWORD count);
-BOOL BASSMIDIDEF(BASS_MIDI_StreamLoadSamples)(HSTREAM handle);
-BOOL BASSMIDIDEF(BASS_MIDI_StreamEvent)(HSTREAM handle, DWORD chan, DWORD event, DWORD param);
-DWORD BASSMIDIDEF(BASS_MIDI_StreamEvents)(HSTREAM handle, DWORD mode, const void *events, DWORD length);
-DWORD BASSMIDIDEF(BASS_MIDI_StreamGetEvent)(HSTREAM handle, DWORD chan, DWORD event);
-DWORD BASSMIDIDEF(BASS_MIDI_StreamGetEvents)(HSTREAM handle, int track, DWORD filter, BASS_MIDI_EVENT *events);
-DWORD BASSMIDIDEF(BASS_MIDI_StreamGetEventsEx)(HSTREAM handle, int track, DWORD filter, BASS_MIDI_EVENT *events, DWORD start, DWORD count);
-BOOL BASSMIDIDEF(BASS_MIDI_StreamGetPreset)(HSTREAM handle, DWORD chan, BASS_MIDI_FONT *font);
-HSTREAM BASSMIDIDEF(BASS_MIDI_StreamGetChannel)(HSTREAM handle, DWORD chan);
-BOOL BASSMIDIDEF(BASS_MIDI_StreamSetFilter)(HSTREAM handle, BOOL seeking, MIDIFILTERPROC *proc, void *user);
-
-HSOUNDFONT BASSMIDIDEF(BASS_MIDI_FontInit)(const void *file, DWORD flags);
-HSOUNDFONT BASSMIDIDEF(BASS_MIDI_FontInitUser)(const BASS_FILEPROCS *procs, void *user, DWORD flags);
-BOOL BASSMIDIDEF(BASS_MIDI_FontFree)(HSOUNDFONT handle);
-BOOL BASSMIDIDEF(BASS_MIDI_FontGetInfo)(HSOUNDFONT handle, BASS_MIDI_FONTINFO *info);
-BOOL BASSMIDIDEF(BASS_MIDI_FontGetPresets)(HSOUNDFONT handle, DWORD *presets);
-const char *BASSMIDIDEF(BASS_MIDI_FontGetPreset)(HSOUNDFONT handle, int preset, int bank);
-BOOL BASSMIDIDEF(BASS_MIDI_FontLoad)(HSOUNDFONT handle, int preset, int bank);
-BOOL BASSMIDIDEF(BASS_MIDI_FontLoadEx)(HSOUNDFONT handle, int preset, int bank, DWORD length, DWORD flags);
-BOOL BASSMIDIDEF(BASS_MIDI_FontUnload)(HSOUNDFONT handle, int preset, int bank);
-BOOL BASSMIDIDEF(BASS_MIDI_FontCompact)(HSOUNDFONT handle);
-BOOL BASSMIDIDEF(BASS_MIDI_FontPack)(HSOUNDFONT handle, const void *outfile, const void *encoder, DWORD flags);
-BOOL BASSMIDIDEF(BASS_MIDI_FontUnpack)(HSOUNDFONT handle, const void *outfile, DWORD flags);
-DWORD BASSMIDIDEF(BASS_MIDI_FontFlags)(HSOUNDFONT handle, DWORD flags, DWORD mask);
-BOOL BASSMIDIDEF(BASS_MIDI_FontSetVolume)(HSOUNDFONT handle, float volume);
-float BASSMIDIDEF(BASS_MIDI_FontGetVolume)(HSOUNDFONT handle);
-
-DWORD BASSMIDIDEF(BASS_MIDI_ConvertEvents)(const BYTE *data, DWORD length, BASS_MIDI_EVENT *events, DWORD count, DWORD flags);
-
-BOOL BASSMIDIDEF(BASS_MIDI_InGetDeviceInfo)(DWORD device, BASS_MIDI_DEVICEINFO *info);
-BOOL BASSMIDIDEF(BASS_MIDI_InInit)(DWORD device, MIDIINPROC *proc, void *user);
-BOOL BASSMIDIDEF(BASS_MIDI_InFree)(DWORD device);
-BOOL BASSMIDIDEF(BASS_MIDI_InStart)(DWORD device);
-BOOL BASSMIDIDEF(BASS_MIDI_InStop)(DWORD device);
-
-#ifdef __cplusplus
-}
-
-static inline BOOL BASS_MIDI_StreamSetFonts(HSTREAM handle, const BASS_MIDI_FONTEX *fonts, DWORD count)
-{
-	return BASS_MIDI_StreamSetFonts(handle, (const void*)fonts, count | BASS_MIDI_FONT_EX);
-}
-
-static inline BOOL BASS_MIDI_StreamSetFonts(HSTREAM handle, const BASS_MIDI_FONTEX2 *fonts, DWORD count)
-{
-	return BASS_MIDI_StreamSetFonts(handle, (const void*)fonts, count | BASS_MIDI_FONT_EX2);
-}
-
-static inline DWORD BASS_MIDI_StreamGetFonts(HSTREAM handle, BASS_MIDI_FONTEX *fonts, DWORD count)
-{
-	return BASS_MIDI_StreamGetFonts(handle, (void*)fonts, count | BASS_MIDI_FONT_EX);
-}
-
-static inline DWORD BASS_MIDI_StreamGetFonts(HSTREAM handle, BASS_MIDI_FONTEX2 *fonts, DWORD count)
-{
-	return BASS_MIDI_StreamGetFonts(handle, (void*)fonts, count | BASS_MIDI_FONT_EX2);
-}
-
-#ifdef _WIN32
-static inline HSTREAM BASS_MIDI_StreamCreateFile(BOOL mem, const WCHAR *file, QWORD offset, QWORD length, DWORD flags, DWORD freq)
-{
-	return BASS_MIDI_StreamCreateFile(mem, (const void*)file, offset, length, flags | BASS_UNICODE, freq);
-}
-
-static inline HSTREAM BASS_MIDI_StreamCreateURL(const WCHAR *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user, DWORD freq)
-{
-	return BASS_MIDI_StreamCreateURL((const char*)url, offset, flags | BASS_UNICODE, proc, user, freq);
-}
-
-static inline HSOUNDFONT BASS_MIDI_FontInit(const WCHAR *file, DWORD flags)
-{
-	return BASS_MIDI_FontInit((const void*)file, flags|BASS_UNICODE);
-}
-
-static inline BOOL BASS_MIDI_FontPack(HSOUNDFONT handle, const WCHAR *outfile, const WCHAR *encoder, DWORD flags)
-{
-	return BASS_MIDI_FontPack(handle, (const void*)outfile, (const void*)encoder, flags | BASS_UNICODE);
-}
-
-static inline BOOL BASS_MIDI_FontUnpack(HSOUNDFONT handle, const WCHAR *outfile, DWORD flags)
-{
-	return BASS_MIDI_FontUnpack(handle, (const void*)outfile, flags | BASS_UNICODE);
-}
-#endif
-#endif
-
-#ifdef __OBJC__
-#undef BOOL
-#endif
-
-#endif

+ 0 - 689
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bassmidi.txt

@@ -1,689 +0,0 @@
-BASSMIDI 2.4
-Copyright (c) 2006-2022 Un4seen Developments Ltd. All rights reserved.
-
-Files that you should have found in the BASSMIDI package
-========================================================
-Win32 version
--------------
-BASSMIDI.TXT    This file
-BASSMIDI.DLL    BASSMIDI module
-BASSMIDI.CHM    BASSMIDI documentation
-X64\
-  BASSMIDI.DLL    64-bit BASSMIDI module
-C\              C/C++ API and examples...
-  BASSMIDI.H      BASSMIDI C/C++ header file
-  BASSMIDI.LIB    BASSMIDI import library
-  BASSMIDI.SLN    Visual Studio solution for examples
-  MAKEFILE        Makefile for examples
-  MAKEFILE.IN     Makefile helper macros
-  X64\
-    BASSMIDI.LIB    64-bit BASSMIDI import library
-  MIDITEST\       MIDI playback example
-    ...
-  SF2PACK\        Soundfont packer
-    ...
-  SYNTH\          Real-time MIDI example
-    ...
-  BIN\            Precompiled examples
-    MIDITEST.EXE
-    SF2PACK.EXE
-    SYNTH.EXE
-VB\             Visual Basic API and examples...
-  BASSMIDI.BAS    BASSMIDI Visual Basic module
-  MIDITEST\       MIDI playback example
-    ...
-DELPHI\         Delphi API and examples...
-  BASSMIDI.PAS    BASSMIDI Delphi unit
-  MIDITEST\       MIDI playback example
-    ...
-  SYNTH\          Real-time MIDI example
-    ...
-
-NOTE: You may need to "Unblock" the BASSMIDI.CHM file in its "Properties" to
-      view it on Windows 7. The documentation can also be viewed online at
-      the BASS website.
-
-NOTE: To run the example EXEs, first you will have to copy BASSMIDI.DLL and
-      BASS.DLL into the same directory as them.
-
-NOTE: To build the examples, you will need to copy the BASS API into the
-      same directory as the BASSMIDI API.
-
-NOTE: The Delphi and VB examples may not always be up to date with the C
-      examples, so the latter should be preferred as references if possible.
-
-macOS version
--------------
-BASSMIDI.TXT    This file
-LIBBASSMIDI.DYLIB  BASSMIDI module
-BASSMIDI.CHM    BASSMIDI documentation
-BASSMIDI.H      BASSMIDI C/C++ header file
-BASSMIDI.XCODEPROJ  Xcode project for examples
-MIDITEST\       MIDI playback example
-  ...
-SF2PACK\        Soundfont packer
-  ...
-SYNTH\          Real-time MIDI example
-  ...
-
-NOTE: To build the examples, you will need to copy the BASS API into the
-      same directory as the BASSMIDI API.
-
-Linux version
--------------
-BASSMIDI.TXT    This file
-LIBBASSMIDI.SO  BASSMIDI module
-BASSMIDI.CHM    BASSMIDI documentation
-BASSMIDI.H      BASSMIDI C/C++ header file
-MAKEFILE        Makefile for examples
-MAKEFILE.IN     Makefile helper macros
-X64\
-  LIBBASSMIDI.SO  64-bit BASSMIDI module
-MIDITEST\       MIDI playback example
-  ...
-SF2PACK\        Soundfont packer
-  ...
-SYNTH\          Real-time MIDI example
-  ...
-
-NOTE: To build the examples, you will need to copy the BASS API into the
-      same directory as the BASSMIDI API.
-
-Android version
----------------
-BASSMIDI.TXT    This file
-BASSMIDI.CHM    BASSMIDI documentation
-LIBS\           BASSMIDI modules
-  ...
-C\              C/C++ API...
-  BASSMIDI.H      BASSMIDI C/C++ header file
-JAVA\COM\UN4SEEN\BASS\
-  BASSMIDI.JAVA   BASSMIDI Java class
-EXAMPLES\       Java examples
-  BUILD.GRADLE    Android Studio build script for examples
-  SETTINGS.GRADLE
-  PROGUARD-BASS.PRO
-  MIDITEST\       MIDI playback example
-    ...
-
-NOTE: To build the examples, you will need to copy the BASS API into the
-      same directory as the BASSMIDI API.
-
-iOS version
------------
-BASSMIDI.TXT    This file
-BASSMIDI.XCFRAMEWORK  BASSMIDI framework
-BASSMIDI.CHM    BASSMIDI documentation
-BASSMIDI.H      BASSMIDI C/C++ header file
-
-
-What's the point?
-=================
-BASSMIDI is an extension to the BASS audio library, enabling the playing of
-MIDI files and custom event sequences, using SF2 (including SF2PACK and SF3)
-and/or SFZ soundfonts to provide the sounds. MIDI input is also supported.
-
-
-Requirements
-============
-BASS 2.4 is required.
-
-
-Using BASSMIDI
-==============
-The MIDI format is used in very much the same way as any of the built-in BASS
-stream formats; simply call the MIDI stream creation function instead of the
-BASS built-in functions. The BASS plugin system (see BASS_PluginLoad) is also
-supported.
-
-SF2 and SFZ soundfonts are used to provide the sounds. There are several
-soundfonts available on the internet, including a couple on the BASS webpage.
-On Windows, the Creative 28MB (28MBGM.SF2), 8MB (CT8MGM.SF2), 4MB (CT4MGM.SF2),
-or 2MB (CT2MGM.SF2) soundfont will be used by default when present in the
-Windows system directory.
-
-The usage information in the BASS.TXT file (from the BASS package) is also
-applicable to BASSMIDI and other add-ons.
-
-TIP: The BASSMIDI.CHM file should be put in the same directory as the BASS.CHM
-     file, so that the BASSMIDI documentation can be accessed from within the
-     BASS documentation.
-
-iOS version
------------
-The CoreMIDI framework is required for MIDI input, so that should be added to
-the "Link Binary With Libraries" build phase in Xcode.
-
-
-Latest Version
-==============
-The latest versions of BASSMIDI & BASS can be found at the BASS website:
-
-	www.un4seen.com
-
-
-Licence
-=======
-BASSMIDI is free to use with BASS.
-
-TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, BASSMIDI IS PROVIDED
-"AS IS", WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
-INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY
-AND/OR FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS SHALL NOT BE HELD
-LIABLE FOR ANY DAMAGE THAT MAY RESULT FROM THE USE OF BASSMIDI. YOU USE
-BASSMIDI ENTIRELY AT YOUR OWN RISK.
-
-Usage of BASSMIDI indicates that you agree to the above conditions.
-
-All trademarks and other registered names contained in the BASSMIDI
-package are the property of their respective owners.
-
-
-History
-=======
-These are the major (and not so major) changes at each version stage.
-There are of course bug fixes and other little improvements made along
-the way too! To make upgrading simpler, all functions affected by a
-change to the BASSMIDI interface are listed.
-
-2.4.14 - 3/5/2022
------------------
-* Support for Key On Velocity to startAddrsOffset/modEnvToFilterFc and CC21-24 to initialFilterFc/
-  initialAttenuation/attackVolEnv/decayVolEnv/releaseVolEnv/releaseModEnv/modEnvToFilterFc SF2 modulators
-	BASS_MIDI_FontInit/User
-* Support for all Key On Velocity to initialAttenuation SF2 modulator curve types
-	BASS_MIDI_FontInit/User
-* Support for SF3 (compressed SF2) soundfonts
-	BASS_MIDI_FontInit/User
-* Soundfont flag setting/retrieval
-	BASS_MIDI_FontFlags
-* Retrieval of currently loading samples
-	BASS_CONFIG_MIDI_SAMPLELOADING (BASS_GetConfig option)
-* Channel-specific soundfont configuration
-	BASS_MIDI_FONT_EX2 (BASS_MIDI_StreamSetFonts/GetFonts flag)
-	BASS_MIDI_FONTEX2 structure
-* MIDI port meta-event support (for more than 16 channels)
-	BASS_MIDI_StreamCreateFile/User/URL
-	BASS_MIDI_StreamEvents
-	BASS_MIDI_ConvertEvents
-* Asynchronous processing of live events
-	BASS_MIDI_ASYNC (BASS_MIDI_StreamCreate/Events/File/User/URL flag)
-	BASS_MIDI_EVENTS_ASYNC (BASS_MIDI_StreamEvents flag)
-	BASS_MIDI_EVENTS_FLUSH (BASS_MIDI_StreamEvents flag)
-	SYNTH example updated
-* Filtering of live events
-	BASS_MIDI_EVENTS_FILTER (BASS_MIDI_StreamEvents flag)
-* Improved reverb effect
-* Reverb/chorus levels raised (closer to Roland/Yamaha levels)
-* Current reverb/chorus type retrieval
-	MIDI_EVENT_REVERB_MACRO (BASS_MIDI_StreamGetEvent)
-	MIDI_EVENT_CHORUS_MACRO (BASS_MIDI_StreamGetEvent)
-* Treat soundfont reverb/chorus levels as minimums
-	BASS_MIDI_FONT_MINFX (BASS_MIDI_FontInit/User/Flags flag)
-* Default per-drum reverb/chorus levels now apply in all modes and can be disabled
-	BASS_MIDI_NODRUMPARAM (BASS_MIDI_StreamCreate/Events/File/User/URL flag)
-* Default drum channel configuration
-	BASS_EVENT_DEFDRUMS (BASS_MIDI_StreamEvent/s and BASS_MIDI_StreamCreateEvents)
-* Support for master tuning
-	MIDI_EVENT_MASTER_FINETUNE/COARSETUNE (BASS_MIDI_StreamEvent/s)
-* Omni-on/off (CC124/125) are treated as all-notes-off (CC123)
-	BASS_MIDI_StreamCreateFile/User/URL
-	BASS_MIDI_StreamEvents
-	BASS_MIDI_ConvertEvents
-* 16 point sinc interpolation support on ARM platforms with NEON
-	BASS_ATTRIB_MIDI_SRC (BASS_ChannelSetAttribute option)
-* Version number retrieval
-	BASS_MIDI_GetVersion
-* BASS_CONFIG_MIDI_SFZHEAD value changed (was same as BASS_CONFIG_MIDI_SAMPLEREAD)
-	BASS_CONFIG_MIDI_SFZHEAD (BASS_SetConfigPtr option)
-* MIDI implementation chart added to documentation
-
-2.4.13 - 16/9/2020
-------------------
-* Vibrato rate/depth/delay adjustment
-	MIDI_EVENT_VIBRATO_RATE/DEPTH/DELAY (BASS_MIDI_StreamEvent/s)
-* Support for Key Number to initialAttenuation/initialFilterFc/pan and Key On Velocity
-  to decayVolEnv/releaseVolEnv SF2 modulators
-	BASS_MIDI_FontInit/User
-* Support for amp_keycenter/amp_keytrack/ampeg_vel2release/delay_beats/fil_keycenter/
-  fil_keytrack/locc67/hicc67/pan_keycenter/pan_keytrack/sw_default/sw_last/sw_lokey/
-  sw_lolast/sw_hikey/sw_hilast SFZ opcodes
-	BASS_MIDI_FontInit/User
-* Support for global and master headers and #define directive in SFZ files
-	BASS_MIDI_FontInit/User
-* SFZ files share memory for common sample files
-	BASS_MIDI_FontInit/User
-* Partial sample loading and unloading
-	BASS_MIDI_FontLoadEx
-	SYNTH example updated
-* Non-interpolated resampling option
-	BASS_ATTRIB_MIDI_SRC (BASS_ChannelSetAttribute option)
-* Tempo modification attribute
-	BASS_ATTRIB_MIDI_SPEED (BASS_ChannelSetAttribute option)
-	MIDITEST example updated
-* Mix level control
-	BASS_ATTRIB_MIDI_VOL (BASS_ChannelSetAttribute option)
-* Reverb level modification
-	BASS_ATTRIB_MIDI_REVERB (BASS_ChannelSetAttribute option)
-* Global SFZ headers
-	BASS_CONFIG_MIDI_SFZHEAD (BASS_SetConfigPtr option)
-* Linear volume envelopes option
-	BASS_MIDI_FONT_LINDECVOL (BASS_MIDI_FontInit/User flag)
-* Disabling of sample ramping-in
-	BASS_MIDI_FONT_NORAMPIN (BASS_MIDI_FontInit/User flag)
-* Disabling of Creative/SoundBlaster hardware limit emulation
-	BASS_MIDI_FONT_NOLIMITS	(BASS_MIDI_FontInit flag)
-* Duplicate soundfonts will be reloaded instead of shared if modified in the meantime
-	BASS_MIDI_FontInit
-* Memory-mapped support for default soundfont option
-	BASS_CONFIG_MIDI_DEFFONT
-* Retrieval of total memory usage for sample data
-	BASS_CONFIG_MIDI_SAMPLEMEM (BASS_GetConfig option)
-* Total sample data size available for SFZ files
-	BASS_MIDI_FontGetInfo
-* Adjustable asynchronous sample loading chunks
-	BASS_CONFIG_MIDI_SAMPLEREAD (BASS_SetConfig option)
-* CPU usage limiting is enabled by default during playback
-	BASS_MIDI_StreamCreate/Events/File/User/URL
-	BASS_ATTRIB_MIDI_CPU (BASS_ChannelSetAttribute option)
-* Option to limit sample loading waiting without killing voices
-	BASS_ATTRIB_MIDI_CPU (BASS_ChannelSetAttribute option)
-* Tick-based timing for realtime event streams
-	BASS_MIDI_StreamCreate
-	BASS_MIDI_StreamEvents
-	BASS_ATTRIB_MIDI_PPQN (BASS_ChannelSetAttribute option)
-* 48000 Hz soundfont data encoding option
-	BASS_MIDI_PACK_48KHZ (BASS_MIDI_FontPack flag)
-* macOS examples rewritten in Objective-C/Cocoa
-
-2.4.12 - 9/11/2018
-------------------
-* Support for more than 16 MIDI channels in custom event sequences
-	BASS_MIDI_StreamCreateEvents
-* Absolute timing option for custom events
-	BASS_MIDI_EVENTS_ABSTIME (BASS_MIDI_StreamEvents flag)
-* Retrieval of note-on events
-	MIDI_EVENT_NOTES (BASS_MIDI_StreamGetEvents/Ex filter)
-* Soundfont config can be modified without stopping currently playing notes
-	BASS_MIDI_StreamSetFonts
-* Memory-mapped soundfonts can be preloaded/mapped
-	BASS_MIDI_FontLoad
-* Support for Key On Velocity to initialAttenuation SF2 modulators
-	BASS_MIDI_FontInit/User
-* Linear attack phase option for SF2 modulation envelopes
-	BASS_MIDI_FONT_LINATTMOD (BASS_MIDI_FontInit/User flag)
-* The attack phase of SFZ pitch/filter envelopes is now linear instead of convex
-* Support for trigger/rt_decay/delay/amplfo_fade/fillfo_fade/pitchlfo_fade/pitch_random/
-  xfin_lokey/xfin_hikey/xfout_lokey/xfout_hikey/xf_keycurve/xfin_lovel/xfin_hivel/
-  xfout_lovel/xfout_hivel/xf_velcurve SFZ opcodes
-	BASS_MIDI_FontInit/User
-* Support for separate amplifier/filter/pitch LFOs in SFZ
-	BASS_MIDI_FontInit/User
-* Support for UTF-8 sample SFZ opcodes on Windows (already on other platforms)
-	BASS_MIDI_FontInit/User
-* Support for #include directive in SFZ files
-	BASS_MIDI_FontInit
-* SFZ files are no longer kept open/locked after being loaded
-	BASS_MIDI_FontInit
-* Samples given more time to load asynchronously when CPU usage is low
-	BASS_ATTRIB_MIDI_CPU (BASS_ChannelSetAttribute option)
-* BASS_MIDI_SINCINTER flag deprecated in favour of BASS_ATTRIB_MIDI_SRC attribute
-	BASS_MIDI_StreamCreate/Events/File/User/URL
-* Smoother low-pass filter activation and deactivation
-* Fix for transpose/tune SFZ opcodes with encoded samples
-
-2.4.11 - 30/3/2017
-------------------
-* Event modification/filtering
-	BASS_MIDI_StreamSetFilter
-	MIDIFILTERPROC
-* Simpler tempo modification
-	MIDI_EVENT_SPEED (BASS_MIDI_StreamEvent)
-	MIDITEST example updated
-* Checking whether individual notes are playing
-	MIDI_EVENT_NOTE (BASS_MIDI_StreamGetEvent)
-* Retrieval of total number of notes playing in a channel
-	MIDI_EVENT_NOTES (BASS_MIDI_StreamGetEvent)
-* Retrieval of currently active voices in a channel
-	MIDI_EVENT_VOICES (BASS_MIDI_StreamGetEvent)
-* Retrieval of currently in use presets
-	BASS_MIDI_StreamGetPreset
-* SFZ filenames are used as preset names
-	BASS_MIDI_FontGetPreset
-* Support for loop info in FLAC samples used with SFZ (requires BASSFLAC 2.4.3)
-* Faster loading of very large MIDI files
-	BASS_MIDI_StreamCreateFile/User/URL
-* Faster unfiltered event counting
-	BASS_MIDI_StreamGetEvents/Ex
-	BASS_MIDI_ConvertEvents
-* 24-bit paramater passed to MIDI_EVENT_TEMPO event sync callbacks
-	BASS_SYNC_MIDI_EVENT (BASS_ChannelSetSync type)
-* When getting the number of events, only those in the specified range are counted
-	BASS_MIDI_StreamGetEventsEx
-* Invalid event types in custom sequences will give an error instead of being ignored
-	BASS_MIDI_StreamCreateEvents
-
-2.4.10 - 8/12/2016
-------------------
-* 16 point sinc interpolation option
-	BASS_ATTRIB_MIDI_SRC (BASS_ChannelSetAttribute option)
-* Support for lorand/hirand/locc1/hicc1/locc64/hicc64/off_mode/default_path SFZ opcodes
-	BASS_MIDI_FontInit/User
-* Support for Key On Velocity to initialFilterFc/attackVolEnv SF2 modulators
-	BASS_MIDI_FontInit/User
-* Conversion of raw MIDI data to BASS_MIDI_EVENT
-	BASS_MIDI_ConvertEvents
-* Modulation (CC1) destination control
-	MIDI_EVENT_MOD_VIBRATO/PITCH/FILTER/VOLUME (BASS_MIDI_StreamEvent/s)
-	MIDI_EVENT_MODRANGE superseded by MIDI_EVENT_MOD_VIBRATO
-* Sostenuto
-	MIDI_EVENT_SOSTENUTO (BASS_MIDI_StreamEvent/s)
-* Legato channel mode
-	MIDI_EVENT_MODE (BASS_MIDI_StreamEvent)
-* Partial retrieval of events
-	BASS_MIDI_StreamGetEventsEx
-* Bulk MIDI state retrieval/setting
-	BASS_ATTRIB_MIDI_STATE (BASS_ChannelGet/SetAttributeEx option)
-* Support for delaying custom events, including delta-time info in raw MIDI data
-	BASS_MIDI_EVENTS_TIME (BASS_MIDI_StreamEvents flag)
-* Cancellation of pending custom events
-	BASS_MIDI_EVENTS_CANCEL (BASS_MIDI_StreamEvents flag)
-* Marker for the start of each track in SMF2 files
-	BASS_MIDI_MARK_TRACKSTART (BASS_MIDI_StreamGetMark type)
-* Ignoring of soundfont effect levels
-	BASS_MIDI_FONT_NOFX (BASS_MIDI_FontInit/Ex flag)
-* Maximum voice limit increased to 100000
-	BASS_CONFIG_MIDI_VOICES (BASS_SetConfig option)
-	BASS_ATTRIB_MIDI_VOICES (BASS_ChannelSetAttribute option)
-* Unicode support for default soundfont option on Windows
-	BASS_CONFIG_MIDI_DEFFONT
-* BASS_CONFIG_UNICODE option support for input device names
-	BASS_MIDI_InGetDeviceInfo
-* Improved seeking with MIDI files that have events for a channel in multiple tracks
-	BASS_ChannelSetPosition
-* Fix for 2GB size limit when unpacking a soundfont on Windows
-	BASS_MIDI_FontUnpack
-
-2.4.9 - 4/12/2014
------------------
-* SFZ soundfont support
-	BASS_MIDI_FontInit/User
-* Support for XG drums in bank 127 of SF2 soundfonts
-	BASS_MIDI_FONT_XGDRUMS (BASS_MIDI_FontInit/Ex flag)
-* Key pressure/aftertouch support
-	MIDI_EVENT_KEYPRES (BASS_MIDI_StreamEvent/s)
-	MIDI_EVENT_KEYPRES_VIBRATO/PITCH/FILTER/VOLUME (BASS_MIDI_StreamEvent/s)
-* 3rd effect path for custom processing
-	BASS_MIDI_CHAN_USERFX (BASS_MIDI_StreamGetChannel option)
-	MIDI_EVENT_USERFX (BASS_MIDI_StreamEvent/s)
-	MIDI_EVENT_USERFX_LEVEL (BASS_MIDI_StreamEvent/s)
-	MIDI_EVENT_USERFX_REVERB (BASS_MIDI_StreamEvent/s)
-	MIDI_EVENT_USERFX_CHORUS (BASS_MIDI_StreamEvent/s)
-* Custom reverb/chorus effect processing
-	BASS_MIDI_CHAN_CHORUS/REVERB (BASS_MIDI_StreamGetChannel options)
-* Custom channel processing output routed to reverb/chorus/custom effects
-	BASS_MIDI_StreamGetChannel
-* Default drum reverb/chorus levels set to XG spec in XG mode (GS/GM modes too)
-	MIDI_EVENT_DRUM_REVERB/CHORUS (BASS_MIDI_StreamEvent/s)
-* Decay time event
-	MIDI_EVENT_DECAY (BASS_MIDI_StreamEvent/s)
-* Support for up to 65536 presets per bank
-	BASS_MIDI_StreamSetFonts
-	MIDI_EVENT_PROGRAM (BASS_MIDI_StreamEvent/s)
-* Input ports to receive MIDI data from other software on Linux
-	BASS_MIDI_InInit
-	BASS_CONFIG_MIDI_IN_PORTS (BASS_SetConfig option)
-	SYNTH example updated
-* Single note releasing when there are overlapping instances of the same note
-	BASS_MIDI_NOTEOFF1 (BASS_MIDI_StreamCreateFile/User/URL flag)
-* Ignoring of system resets with unchanged mode
-	BASS_MIDI_NOSYSRESET (BASS_MIDI_StreamCreateFile/User/URL flag)
-	MIDI_EVENT_SYSTEM (BASS_MIDI_StreamEvent/s)
-* Disabling of running status
-	BASS_MIDI_EVENTS_NORSTATUS (BASS_MIDI_StreamEvents flag)
-* Maximum voice limit increased to 1000
-	BASS_CONFIG_MIDI_VOICES (BASS_SetConfig option)
-	BASS_ATTRIB_MIDI_VOICES (BASS_ChannelSetAttribute option)
-* Reduction of 24-bit data to 16-bit when packing soundfont samples
-	BASS_MIDI_PACK_16BIT (BASS_MIDI_FontPack flag)
-* Support for remaining SF2 generators: fixed key, fixed velocity, key to vol/mod envelope hold/decay
-* Fix for multi-track custom event sequence stream creation
-	BASS_MIDI_StreamCreateEvents
-
-2.4.8 - 2/5/2013
-----------------
-* User file soundfont loading
-	BASS_MIDI_FontInitUser
-* Retrieval of all of a soundfont's preset numbers
-	BASS_MIDI_FontGetPresets
-* More flexible soundfont preset mapping
-	BASS_MIDI_FONT_EX (BASS_MIDI_StreamSetFonts/GetFonts flag)
-	BASS_MIDI_FONTEX structure
-* Bank LSB controller support
-	MIDI_EVENT_BANK_LSB (BASS_MIDI_StreamEvent/s)
-	BASS_MIDI_FONTEX structure
-* Modulation depth range control
-	MIDI_EVENT_MODRANGE (BASS_MIDI_StreamEvent/s)
-* Channel pressure destination control
-	MIDI_EVENT_CHANPRES_VIBRATO/PITCH/FILTER/VOLUME (BASS_MIDI_StreamEvent/s)
-* Unhandled controller event
-	MIDI_EVENT_CONTROL (BASS_MIDI_StreamEvent/s)
-* Reverb send level default changed to 40 (was 0)
-	MIDI_EVENT_REVERB (BASS_MIDI_StreamEvent/s)
-* Retrieval of events from all tracks at once
-	BASS_MIDI_StreamGetEvents
-* Copyright/instrument/track name markers
-	BASS_MIDI_MARK_COPY (BASS_MIDI_StreamGetMark type)
-	BASS_MIDI_MARK_INST (BASS_MIDI_StreamGetMark type)
-	BASS_MIDI_MARK_TRACK (BASS_MIDI_StreamGetMark type)
-* Retrieval of all markers at once
-	BASS_MIDI_StreamGetMarks
-* New sync type that supports all marker types
-	BASS_SYNC_MIDI_MARK (BASS_ChannelSetSync type)
-* Non-removal of empty space at the end of a MIDI file
-	BASS_MIDI_NOCROP (BASS_MIDI_StreamCreateFile/User/URL flag)
-* Omission of a WAVE header when packing soundfont samples
-	BASS_MIDI_PACK_NOHEAD (BASS_MIDI_FontPack flag)
-* Streams created via the plugin system use the output device's sample rate
-	BASS_StreamCreateFile/etc
-* Automatic BASS_UNICODE flag use in C++ and Delphi
-	BASS_MIDI_StreamCreateFile/URL
-	BASS_MIDI_FontInit/Pack/Unpack
-
-2.4.7 - 29/6/2012
------------------
-* Custom event sequence streams
-	BASS_MIDI_StreamCreateEvents	
-* Sinc interpolated sample mixing
-	BASS_MIDI_SINCINTER (BASS_MIDI_StreamCreate/Events/File/User/URL flag)
-* Asynchronous sample loading
-	BASS_ATTRIB_MIDI_CPU (BASS_ChannelSetAttribute option)
-* Preset unloading
-	BASS_MIDI_FontUnload
-* Note stopping without sustain/decay
-	BASS_EVENT_NOTE (BASS_MIDI_StreamEvent/s)
-* Syncing on all event types
-	BASS_SYNC_MIDI_EVENT (BASS_ChannelSetSync type)
-* Marker tick position retrieval
-	BASS_MIDI_MARK_TICK (BASS_MIDI_StreamGetMark flag)
-* Maximum voice limit increased to 500
-	BASS_CONFIG_MIDI_VOICES (BASS_SetConfig option)
-	BASS_ATTRIB_MIDI_VOICES (BASS_ChannelSetAttribute option)
-* Default voice limit raised to 40 on Android/iOS
-	BASS_CONFIG_MIDI_VOICES (BASS_SetConfig option)
-* Active voice count retrieval
-	BASS_ATTRIB_MIDI_VOICES_ACTIVE (BASS_ChannelGetAttribute option)
-* Use of the device's current output rate
-	BASS_MIDI_StreamCreate/Events/File/User/URL
-* Memory-mapped soundfont loading
-	BASS_MIDI_FONT_MMAP (BASS_MIDI_FontInit flag)
-* Fix for applying multiple events in BASS_MIDI_EVENTS_STRUCT mode
-	BASS_MIDI_StreamEvents
-* Marker sync compatibility (with mixer/splitter/tempo/reverse streams) fix
-	BASS_SYNC_MIDI_MARKER/CUE/LYRIC (BASS_ChannelSetSync types)
-* MIDI sysex input compatibility fix for some drivers on Windows
-	MIDIINPROC
-
-2.4.6 - 30/3/2011
------------------
-* MIDI input device support
-	BASS_MIDI_InGetDeviceInfo
-	BASS_MIDI_InInit
-	BASS_MIDI_InFree
-	BASS_MIDI_InStart
-	BASS_MIDI_InStop
-	MIDIINPROC
-	SYNTH example updated
-* Multiple event processing including support for raw MIDI data
-	BASS_MIDI_StreamEvents
-* CPU usage limiting
-	BASS_ATTRIB_MIDI_CPU (BASS_ChannelSetAttribute option)
-* Scale/octave tuning
-	MIDI_EVENT_SCALETUNING (BASS_MIDI_StreamEvent/s)
-* Soft pedal event
-	MIDI_EVENT_SOFT (BASS_MIDI_StreamEvent/s)
-* Random panning
-	MIDI_EVENT_PAN (BASS_MIDI_StreamEvent/s)
-* System reset event
-	MIDI_EVENT_SYSTEM/EX (BASS_MIDI_StreamEvent/s)
-* Resetting of overridden drum key pan/reverb/chorus back to normal
-	MIDI_EVENT_DRUM_PAN/REVERB/CHORUS (BASS_MIDI_StreamEvent)
-* Retrieval of drum key event values
-	BASS_MIDI_StreamGetEvent
-* All events initialized to a MIDI file's 1st tick values
-	BASS_MIDI_StreamGetEvent
-* Adjustable MIDI channel count
-	BASS_ATTRIB_MIDI_CHANS (BASS_ChannelSetAttribute option)
-* Adjustable voice limit
-	BASS_ATTRIB_MIDI_VOICES (BASS_ChannelSetAttribute option)
-* Preloaded presets are not automatically compacted
-	BASS_MIDI_FontLoad
-	BASS_CONFIG_MIDI_COMPACT (BASS_SetConfig option)
-* Multiple instances of a soundfont
-	BASS_MIDI_FontInit
-* Xcode examples project added for OSX
-
-2.4.5 - 8/2/2010
-----------------
-* Key signature retrieval
-	BASS_MIDI_MARK_KEYSIG (BASS_MIDI_StreamGetMark type)
-	BASS_SYNC_MIDI_KEYSIG (BASS_ChannelSetSync type)
-* Tempo event initialized to MIDI file's 1st tick value
-	MIDI_EVENT_TEMPO (BASS_MIDI_StreamGetEvent)
-* UTF-16 support on OSX
-	BASS_UNICODE (BASS_MIDI_StreamCreateFile/BASS_MIDI_FontInit/Pack/Unpack flag)
-
-2.4.4 - 24/8/2009
------------------
-* Attack & release time events
-	MIDI_EVENT_ATTACK/RELEASE (BASS_MIDI_StreamEvent)
-* Drum key level NRPN event
-	MIDI_EVENT_DRUM_LEVEL (BASS_MIDI_StreamEvent)
-* MIDI file event retrieval
-	BASS_MIDI_StreamGetEvents
-* Time signature retrieval
-	BASS_MIDI_MARK_TIMESIG (BASS_MIDI_StreamGetMark type)
-	BASS_SYNC_MIDI_TIMESIG (BASS_ChannelSetSync type)
-* Default soundfont configuration
-	BASS_CONFIG_MIDI_DEFFONT (BASS_SetConfig option)
-
-2.4.3 - 19/3/2009
------------------
-* Possibility of applying DSP/FX to individual MIDI channels
-	BASS_MIDI_StreamGetChannel
-* Per-track volume control
-	BASS_ATTRIB_MIDI_TRACK_VOL (BASS_ChannelSetAttribute option)
-* Support for all tracks in format 2 MIDI files
-	BASS_MIDI_StreamCreateFile/User/URL
-
-2.4.2 - 28/10/2008
-------------------
-* Decaying of old sound when seeking
-	BASS_MIDI_DECAYSEEK (BASS_MIDI_StreamCreateFile/User/URL flag)
-	MIDITEST example updated (C version)
-* End decaying now also applies when looping
-	BASS_MIDI_DECAYEND (BASS_MIDI_StreamCreateFile/User/URL flag)
-* Support for 28MBGM.SF2 and CT8MGM.SF2 as default soundfonts
-
-2.4.1 - 9/7/2008
-----------------
-* Ticks-per-beat retrieval
-	BASS_ATTRIB_MIDI_PPQN (BASS_ChannelGetAttribute option)
-
-2.4 - 2/4/2008
---------------
-* Tick-based positioning
-	BASS_POS_MIDI_TICK (BASS_ChannelGetLength/GetPosition/SetPosition mode)
-	BASS_SYNC_MIDI_TICK (BASS_ChannelSetSync type)
-* Preset name retrieval
-	BASS_MIDI_FontGetPreset
-* Text markers
-	BASS_MIDI_MARK_TEXT (BASS_MIDI_StreamGetMark type)
-	BASS_SYNC_MIDI_TEXT (BASS_ChannelSetSync type)
-* Individual marker retrieval
-	BASS_MIDI_StreamGetMark
-	BASS_MIDI_StreamGetMarks *removed*
-* Marker index passed to marker sync callbacks
-	BASS_SYNC_MIDI_MARKER/CUE/LYRIC
-* Use of BASS_Init sample rate
-	BASS_MIDI_StreamCreate/File/User/URL
-* Support for updated user file stream system
-	BASS_MIDI_StreamCreateFileUser
-* 64-bit file positioning
-	BASS_MIDI_StreamCreateFile
-* Callback "user" parameters changed to pointers
-	BASS_MIDI_StreamCreateURL
-	BASS_MIDI_StreamCreateFileUser
-
-2.3.0.3 - 10/7/2007
--------------------
-* Syncing on events
-	BASS_SYNC_MIDI_EVENT (BASS_ChannelSetSync type)
-
-2.3.0.2 - 26/2/2007
--------------------
-* Reverb and chorus
-	MIDI_EVENT_REVERB/CHORUS (BASS_MIDI_StreamEvent)
-	MIDI_EVENT_REVERB_TIME/DELAY/LOCUTOFF/HICUTOFF/LEVEL (BASS_MIDI_StreamEvent)
-	MIDI_EVENT_CHORUS_DELAY/DEPTH/RATE/FEEDBACK/LEVEL/REVERB (BASS_MIDI_StreamEvent)
-	BASS_MIDI_NOFX (BASS_MIDI_StreamCreate/File/User/URL flag)
-* Resonant low-pass filters
-	MIDI_EVENT_CUTOFF/RESONANCE (BASS_MIDI_StreamEvent)
-* Portamento
-	MIDI_EVENT_PORTAMENTO/TIME/NOTE (BASS_MIDI_StreamEvent)
-* Fine-tuning
-	MIDI_EVENT_FINETUNE/COARSETUNE (BASS_MIDI_StreamEvent)
-* Drum key specific parameters
-	MIDI_EVENT_DRUM_FINETUNE/COARSETUNE/PAN/REVERB/CHORUS/CUTOFF/RESONANCE (BASS_MIDI_StreamEvent)
-* Support for mono channel mode
-	MIDI_EVENT_MODE (BASS_MIDI_StreamEvent)
-* Support for master volume
-	MIDI_EVENT_MASTERVOL (BASS_MIDI_StreamEvent)
-* Channel level control
-	MIDI_EVENT_MIXLEVEL (BASS_MIDI_StreamEvent)
-* Channel transposing
-	MIDI_EVENT_TRANSPOSE (BASS_MIDI_StreamEvent)
-* Retrieval of current event values
-	BASS_MIDI_StreamGetEvent
-* Soundfont volume control
-	BASS_MIDI_FontSetVolume/GetVolume
-* Track number added to markers and syncs
-	BASS_MIDI_MARK (track member)
-	BASS_SYNC_MIDI_MARKER/CUE/LYRIC
-
-2.3.0.1 - 1/12/2006
--------------------
-* Optionally apply matching soundfonts to all banks
-	BASS_CONFIG_MIDI_AUTOFONT (BASS_SetConfig option)
-* Support for 0 length notes
-
-2.3 - 14/11/2006
-----------------
-* First release
-
-
-Bug reports, Suggestions, Comments, Enquiries, etc
-==================================================
-If you have any of the aforementioned please visit the BASS forum at the
-website.
-

+ 0 - 43
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bassmidi.xcframework/Info.plist

@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>AvailableLibraries</key>
-	<array>
-		<dict>
-			<key>LibraryIdentifier</key>
-			<string>ios-arm64_i386_x86_64-simulator</string>
-			<key>LibraryPath</key>
-			<string>libbassmidi.a</string>
-			<key>SupportedArchitectures</key>
-			<array>
-				<string>arm64</string>
-				<string>i386</string>
-				<string>x86_64</string>
-			</array>
-			<key>SupportedPlatform</key>
-			<string>ios</string>
-			<key>SupportedPlatformVariant</key>
-			<string>simulator</string>
-		</dict>
-		<dict>
-			<key>LibraryIdentifier</key>
-			<string>ios-arm64_armv7_armv7s</string>
-			<key>LibraryPath</key>
-			<string>libbassmidi.a</string>
-			<key>SupportedArchitectures</key>
-			<array>
-				<string>arm64</string>
-				<string>armv7</string>
-				<string>armv7s</string>
-			</array>
-			<key>SupportedPlatform</key>
-			<string>ios</string>
-		</dict>
-	</array>
-	<key>CFBundlePackageType</key>
-	<string>XFWK</string>
-	<key>XCFrameworkFormatVersion</key>
-	<string>1.0</string>
-</dict>
-</plist>

BIN
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bassmidi.xcframework/ios-arm64_armv7_armv7s/libbassmidi.a


BIN
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/BASSMidiPlayer/Source/bassmidi.xcframework/ios-arm64_i386_x86_64-simulator/libbassmidi.a


+ 0 - 20
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Controller/KSCloudViewController.h

@@ -1,20 +0,0 @@
-//
-//  KSCloudViewController.h
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/8.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import "BaseViewController.h"
-#import "CloudSongMessageModel.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface KSCloudViewController : BaseViewController
-
-- (void)configMessage:(CloudSongMessageModel *)songMessage;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 2219
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Controller/KSCloudViewController.m

@@ -1,2219 +0,0 @@
-//
-//  KSCloudViewController.m
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/8.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import "KSCloudViewController.h"
-#import <KSToolLibrary/UIDevice+TFDevice.h>
-#import "AppDelegate.h"
-#import "StaffImageDisplayView.h"
-#import "KYSourceParseManager.h"
-#import <KSToolLibrary/MidiPlayerEngine.h>
-
-#import "CloudControlButton.h"
-#import "KSCloudSettingView.h"
-#import "KSXMLInfoParse.h"
-#import "ScoreAnimationView.h"
-#import "EvaluateResultAlert.h"
-#import "NoWiredTipsAlert.h"
-#import "LFPopupMenu.h"
-#import "KSSliderView.h"
-#import "SoundCheckView.h"
-#import "KSBaseWKWebViewController.h"
-#import <SSZipArchive/SSZipArchive.h>
-#import "CloudHelpView.h"
-#import "CloudFeedbackView.h"
-#import <KSToolLibrary/KSAudioSessionManager.h>
-#import <CloudAccompanyLibrary/KSCloudBeatView.h>
-
-#import <KSToolLibrary/RecordCheckManager.h>
-#import <KSToolLibrary/KSAQRecordManager.h>
-#import <KSToolLibrary/KSWebSocketManager.h>
-#import <CloudAccompanyLibrary/KSVideoRecordManager.h>
-
-#import "TrackChooseView.h"
-
-#define PositionRate (12)    // 图片上点的位置和位置文件的系数
-
-#define Left_Space (37)
-#define Button_Width (34)
-#define Button_Height (60)
-#define Button_Space (20)
-
-#define BACKVIEW_ALPHA (0.6f)
-typedef NS_ENUM(NSInteger, BUTTON_TAG) {
-    BUTTON_TAG_EVALUATING = 1000, // 评测
-    BUTTON_TAG_SELECT,  // 选段
-    BUTTON_TAG_PLAY,    // 播放
-    BUTTON_TAG_SWITCH,  // 切换
-    BUTTON_TAG_REPEAT,  // 重播
-    BUTTON_TAG_SPEED,   // 调速
-    BUTTON_TAG_SETTING, // 设置
-};
-
-typedef NS_ENUM(NSInteger,COLOR_DISPLAYTYPE) {
-    COLOR_DISPLAYTYPE_NOMAL,
-    COLOR_DISPLAYTYPE_PROTECT,
-};
-
-@interface KSCloudViewController ()<PlayerEngineDelegate,KSAQRecordManagerDelegate,KSSliderDelegate,KSAudioSessionManagerDelegate>
-
-@property (nonatomic, strong) KSAudioSessionManager *audioSessionManager;
-
-@property (nonatomic, assign) MetronomeType beatType;
-
-@property (nonatomic, assign) BOOL keepOrientation;
-
-@property (nonatomic, strong) UIView *backView;
-
-@property (nonatomic, strong) UIView *bgColorView; // 容器颜色视图
-
-@property (nonatomic, assign) COLOR_DISPLAYTYPE bgColorType; // 容器颜色类型
-
-@property (nonatomic, strong) UIScrollView *displayScrollView;
-
-@property (nonatomic, strong) UIButton *helpButton; // 帮助按钮
-
-@property (nonatomic, strong) KSSliderView *sliderView;
-
-@property (nonatomic, assign) BOOL scorllEnable;  // 是否能滑动
-
-@property (nonatomic, strong) NSMutableArray *pageArray;
-
-@property (nonatomic, strong) KYSourceParseManager *manager;
-
-@property (nonatomic, assign) CGFloat scaleRate;
-
-@property (nonatomic, assign) CGFloat pageViewHeight;
-
-@property (nonatomic, assign) BOOL isChooseMeasure; // 是否小节选择模式
-
-@property (nonatomic, assign) NSInteger startMeasure;
-
-@property (nonatomic, assign) NSInteger endMeasure;
-
-@property (nonatomic, strong) UIView *cursorView;  // 光标
-
-@property (nonatomic, strong) UIButton *evaluateButton; // 评测按钮
-
-@property (nonatomic, assign) BOOL isEvaluating;  // 是否开启评测模式
-
-@property (nonatomic, strong) MidiPlayerEngine *playerEngine; // player
-
-@property (nonatomic, strong) UIView *headView;
-
-@property (nonatomic, assign) NSInteger lastPlayNodeIndex; // 上次播放的音符序号
-
-@property (nonatomic, strong) NSString *songPath; // 音频文件路径
-
-@property (nonatomic, strong) NSString *songName;  // 曲目名称
-
-@property (nonatomic, assign) BOOL isPlaying; // 是否正在播放的状态
-
-@property (nonatomic, assign) BOOL isNeedRepeat; // 是否需要重复
-
-@property (nonatomic, assign) BOOL soundCheckOn; // 是否校音
-
-@property (nonatomic, assign) BOOL showFinger;   // 显示指法开关
-
-@property (nonatomic, assign) BOOL needShowFinger;   // 是否需要显示指法
-
-@property (nonatomic, assign) BOOL cameraOn;     // 是否开启摄像头
-
-@property (nonatomic, assign) BOOL eyeShieldOn;   // 护眼模式是否开启
-
-@property (nonatomic, assign) BOOL saveVideo;     // 是否保存视频
-
-@property (nonatomic, strong) NSString *level;   // 评测级别
-
-@property (nonatomic, assign) BOOL accompanyOn;   // 是否开启伴奏
-
-@property (nonatomic, assign) NSInteger currentSpeed; // 当前速度
-// 是否发送了musicXML信息
-@property (nonatomic, assign) BOOL hasSendStartMessage;
-
-@property (nonatomic, strong) KSAQRecordManager *AQManager;
-
-@property (nonatomic, strong) KSWebSocketManager *socketManager;
-
-@property (nonatomic, strong) NSMutableDictionary *evaluatParm;
-
-// 评测开始时发送recordStart消息的标识
-@property (nonatomic, assign) BOOL isCompareStart;
-// 校音开始时发送 checkStart消息标识
-@property (nonatomic, assign) BOOL isSoundCheckStart;
-
-// 自定义UI控件容器
-@property (nonatomic, strong) UIView *viewContainer;
-
-@property (nonatomic, strong) KSVideoRecordManager *videoRecordManager;
-
-@property (nonatomic, strong) NSMutableArray *nodeArray;
-
-@property (nonatomic, assign) NSInteger recordId;
-
-@property (nonatomic, strong) EvaluateResultAlert *resultAlert;
-
-@property (nonatomic, strong) NoWiredTipsAlert *wiredAlert;
-
-@property (nonatomic, assign) NSInteger checkPitch;
-
-@property (nonatomic, assign) long long correctTimeInterval;
-
-@property (nonatomic, strong) SoundCheckView *checkView;
-
-@property (nonatomic, strong) CloudSongMessageModel *songMessageSource;
-
-@property (nonatomic, assign) BOOL isVertical;
-
-@property (nonatomic, strong) NSDictionary *fingerImageDic;
-
-@property (nonatomic, strong) NSString *fullDicImage;
-
-@property (nonatomic, strong) UIView *fingerDisplayView;
-
-@property (nonatomic, strong) UIView *fingerContentView;
-
-@property (nonatomic, assign) CGRect defaultFrame;
-
-@property (nonatomic, assign) CGRect resizeFrame;
-
-@property (nonatomic, strong) NSMutableArray *zipFileArray;
-
-@property (nonatomic, strong) CloudFeedbackView *feedbackView;
-
-@property (nonatomic, strong) TrackChooseView *trackChooseView;
-
-@end
-
-@implementation KSCloudViewController
-
-- (NSString *)getSaveZipPath {
-    //  在Documents目录下创建一个名为AudioSpeedFile的文件夹
-    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject] stringByAppendingPathComponent:@"AudioZipFile"];
-    NSLog(@"%@",path);
-    
-    NSFileManager *fileManager = [NSFileManager defaultManager];
-    BOOL isDir = FALSE;
-    BOOL isDirExist = [fileManager fileExistsAtPath:path isDirectory:&isDir];
-    if(!(isDirExist && isDir)) {
-        BOOL bCreateDir = [fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
-        if(!bCreateDir){
-            NSLog(@"创建文件夹失败!");
-        }
-        NSLog(@"创建文件夹成功,文件路径%@",path);
-    }
-    
-    NSLog(@"file path:%@",path);
-    return path;
-}
-
-
-#pragma mark ----- life cycle
-- (void)viewDidLoad {
-    [super viewDidLoad];
-    // Do any additional setup after loading the view.
-    self.ks_prefersNavigationBarHidden = YES;
-    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appEnterBackground) name:@"appEnterBackground" object:nil];
-    self.view.backgroundColor = UIColor.whiteColor;
-    [self displayBaseConfig];
-}
-
-- (void)viewWillAppear:(BOOL)animated {
-    [super viewWillAppear:animated];
-    [self connectSocketService];
-    // 切换到横屏
-    [self changeOrientation:YES];
-    [[UIApplication sharedApplication] setIdleTimerDisabled:YES];
-}
-
-- (void)viewDidAppear:(BOOL)animated {
-    [super viewDidAppear:animated];
-    if (self.songMessageSource != nil) {
-        NSString *filePath = [self getSaveZipPath];
-        NSString *floderName = [[[self.songMessageSource.zipUrl getUrlFileName] componentsSeparatedByString:@"."] firstObject];
-        filePath = [NSString stringWithFormat:@"%@/%@",filePath,floderName];
-        NSError *error = nil;
-        NSArray *folderContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:filePath error:&error];
-        if (folderContents.count == 0) {
-            [self downloadZipFileWithFloderName:floderName];
-        }
-        else {
-            [self configUnZipFilePathWithFloderName:floderName];
-        }
-    }
-}
-
-- (void)viewWillDisappear:(BOOL)animated {
-    [super viewWillDisappear:animated];
-    [[UIApplication sharedApplication] setIdleTimerDisabled:NO];
-    if (_AQManager) {
-        [_AQManager freeAudioQueue];
-        _AQManager = nil;
-    }
-    if (_socketManager) {
-        [self.socketManager SRWebSocketClose];
-        _socketManager = nil;
-    }
-    [self stopSession];
-
-    if (self.keepOrientation == NO) {
-        [self changeOrientation:NO];
-        // 如果退出评测页面 清除 playerEngine
-        if (self.playerEngine) {
-            [self.playerEngine cleanup];
-            self.playerEngine = nil;
-        }
-    }
-    self.keepOrientation = NO;
-}
-
-- (void)changeOrientation:(BOOL)isLandScape {
-    if (isLandScape) {
-        // 切换到横屏
-        AppDelegate* delegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
-        delegate.allowAutoRotate = YES;
-        [UIDevice switchNewOrientation:UIInterfaceOrientationLandscapeRight inController:self];
-    }
-    else {
-        AppDelegate* delegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
-        delegate.allowAutoRotate = NO;
-        [UIDevice switchNewOrientation:UIInterfaceOrientationPortrait inController:self];
-    }
-}
-
-
-#pragma mark ---- 获取和配置曲目相关参数
-- (void)configMessage:(CloudSongMessageModel *)songMessage {
-    self.songMessageSource = songMessage;
-    self.songName = songMessage.examSongName;
-}
-
-- (void)configUnZipFilePathWithFloderName:(NSString *)name {
-    self.zipFileArray = [NSMutableArray array];
-    NSString *filePath = [self getSaveZipPath];
-    filePath = [NSString stringWithFormat:@"%@/%@",filePath,name];
-    NSError *error = nil;
-    NSArray *folderContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:filePath error:&error];
-    for (NSString *fileName in folderContents) {
-        NSString *path = [NSString stringWithFormat:@"%@/%@", filePath, fileName];
-        [self.zipFileArray addObject:path];
-    }
-    NSLog(@"------%@",name);
-    [self querySourceMessage];
-}
-
-- (void)downloadZipFileWithFloderName:(NSString *)name {
-    
-    [LOADING_MANAGER showHUD];
-    [KSNetworkingManager downloadFileRequestWithFileUrl:self.songMessageSource.zipUrl progress:^(int64_t bytesRead, int64_t totalBytes) {
-        
-    } success:^(NSURL * _Nonnull fileUrl) {
-
-        // 解压zip包
-        NSString *filePath = [self getSaveZipPath];
-        BOOL success = [SSZipArchive unzipFileAtPath:fileUrl.path toDestination:filePath];
-        NSLog(@"%d", success);
-        if (success) {
-            [LOADING_MANAGER removeHUD];
-            [self configUnZipFilePathWithFloderName:name];
-        }
-        else {
-            [LOADING_MANAGER removeHUD];
-            [LOADING_MANAGER MBShowAUTOHidingInWindow:@"资源解压失败"];
-        }
-    } faliure:^(NSError * _Nonnull error) {
-        [LOADING_MANAGER removeHUD];
-        [LOADING_MANAGER MBShowAUTOHidingInWindow:@"下载配置资源失败"];
-    }];
-}
-
-- (void)displayBaseConfig {
-    self.beatType = MetronomeType4V4;
-    NSString *savePath = [CloudSongMessageModel getSaveSpeedPath];
-    NSDictionary *speedDic = [NSMutableDictionary dictionaryWithContentsOfFile:savePath];
-    NSInteger speed = [speedDic ks_integerValueForKey:self.songMessageSource.examSongId];
-    if (speed != 0) {
-        self.currentSpeed = speed;
-    }
-    [self queryFingerConfig];
-    [self queryCloudConfig];
-}
-
-- (void)queryFingerConfig {
-    
-    NSDictionary *fingerSubjectDic = [NSMutableDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"SubjectFinger" ofType:@"plist"]];
-    
-    NSDictionary *imageDict = [NSMutableDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"FingerList" ofType:@"plist"]];
-    // 根据当前声部获取对应的音高对应图片
-    NSString *subjectId = self.songMessageSource.subjectId;
-    
-    NSDictionary *subjectDic = [fingerSubjectDic ks_dictionaryValueForKey:subjectId];
-    if (subjectDic) {
-        NSString *subjectName = [subjectDic ks_stringValueForKey:@"name"];
-        BOOL isVertical = [subjectDic ks_boolValueForKey:@"vertical"];
-        self.isVertical = isVertical;
-        
-        NSDictionary *fingerSource = [imageDict ks_dictionaryValueForKey:subjectName];
-        self.fingerImageDic = [NSDictionary dictionaryWithDictionary:fingerSource];
-        
-        NSString *fullImageName = [NSString stringWithFormat:@"%@full",subjectName];
-        UIImage *bgImage = [UIImage imageNamed:fullImageName];
-        
-        CGRect frame = CGRectZero;
-        CGFloat width = bgImage.size.width;
-        CGFloat height = bgImage.size.height;
-        if (isVertical) {
-            CGFloat contentHeight = CGRectGetHeight(self.defaultFrame);
-            if (height > contentHeight) {
-                width = contentHeight / height * width;
-                height = contentHeight;
-            }
-            frame = CGRectMake(CGRectGetWidth(self.defaultFrame) - width, (CGRectGetHeight(self.defaultFrame) - height) / 2.0f, width, height);
-            self.resizeFrame = CGRectMake(0, 0, CGRectGetWidth(self.defaultFrame)-width, CGRectGetHeight(self.defaultFrame));
-        }
-        else {
-            CGFloat contentWidth = CGRectGetWidth(self.defaultFrame);
-            if (width > contentWidth) {
-                height = width / contentWidth * height;
-                width = contentWidth;
-            }
-            
-            frame = CGRectMake((CGRectGetWidth(self.defaultFrame) - width) / 2.0f, CGRectGetHeight(self.defaultFrame) - height, width, height);
-            
-            self.resizeFrame = CGRectMake(0, 0, CGRectGetWidth(self.defaultFrame), CGRectGetHeight(self.defaultFrame) - height);
-        }
-        self.fingerDisplayView = [[UIView alloc] initWithFrame:frame];
-        self.fingerDisplayView.backgroundColor = [UIColor clearColor];
-        UIImageView *bgImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
-        [bgImageView setImage:bgImage];
-        [self.fingerDisplayView addSubview:bgImageView];
-        
-        self.fingerContentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
-        self.fingerContentView.backgroundColor = [UIColor clearColor];
-        [self.fingerDisplayView addSubview:self.fingerContentView];
-    }
-}
-
-- (void)setShowFinger:(BOOL)showFinger {
-    _showFinger = showFinger;
-    if (showFinger && self.fingerImageDic != nil) {
-        self.needShowFinger = YES;
-    }
-    else {
-        self.needShowFinger = NO;
-    }
-}
-
-- (void)queryCloudConfig {
-    NSDictionary *config = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"cloudConfig"];
-    if (config == nil || config.allKeys.count == 0) {
-        NSMutableDictionary *newConfig = [NSMutableDictionary dictionary];
-        [newConfig setValue:@(NO) forKey:@"eyeshield"];
-        [newConfig setValue:@(NO) forKey:@"soundCheck"];
-        [newConfig setValue:@(NO) forKey:@"cameraOn"];
-        [newConfig setValue:@(YES) forKey:@"repeatOn"];
-        [newConfig setValue:@(YES) forKey:@"showFinger"];
-        [newConfig setValue:@"ADVANCED" forKey:@"level"];
-        [newConfig setValue:@(YES) forKey:@"accompanyOn"];
-        [newConfig setValue:@(NO) forKey:@"save"];
-        [newConfig setValue:self.songMessageSource.behaviorId forKey:@"behaviorId"];
-        [newConfig setValue:@"" forKey:@"tips-status"];
-        [[NSUserDefaults standardUserDefaults] setObject:newConfig forKey:@"cloudConfig"];
-        [[NSUserDefaults standardUserDefaults] synchronize];
-        config = [NSDictionary dictionaryWithDictionary:newConfig];
-    }
-    
-    self.eyeShieldOn = [config ks_boolValueForKey:@"eyeshield"];
-    self.soundCheckOn = [config ks_boolValueForKey:@"soundCheck"];
-    self.cameraOn = [config ks_boolValueForKey:@"cameraOn"];
-    self.isNeedRepeat = [config ks_boolValueForKey:@"repeatOn"];
-    self.showFinger = [config ks_boolValueForKey:@"showFinger"];
-    self.level = [config ks_stringValueForKey:@"level"];
-    self.saveVideo = [config ks_boolValueForKey:@"save"];
-    self.accompanyOn = [config ks_boolValueForKey:@"accompanyOn"];
-    
-    NSMutableDictionary *saveConfig = [NSMutableDictionary dictionaryWithDictionary:config];
-    [saveConfig setValue:self.songMessageSource.behaviorId forKey:@"behaviorId"];
-    [[NSUserDefaults standardUserDefaults] setObject:saveConfig forKey:@"cloudConfig"];
-    [[NSUserDefaults standardUserDefaults] synchronize];
-    
-}
-
-- (void)querySourceMessage {
-    
-    dispatch_async(dispatch_queue_create("CloudSource", DISPATCH_QUEUE_SERIAL), ^{
-        // 未选择小节设置为-1;
-        self.startMeasure = -1;
-        self.endMeasure = -1;
-        NSString *measurePath = @"";
-        NSString *nodeSourePath = @"";
-        NSString *xmlFile = @"";
-        NSString *songPath = @"";
-        for (NSString *filePath in self.zipFileArray) {
-            if ([filePath containsString:@".mpos"]) {
-                measurePath = filePath;
-            }
-            else if ([filePath containsString:@".spos"]) {
-                nodeSourePath = filePath;
-            }
-            else if ([filePath containsString:@".musicxml"] || [filePath containsString:@".xml"]) {
-                xmlFile = filePath;
-            }
-            else if ([filePath containsString:@".mid"]) {
-                songPath = filePath;
-                self.songPath = songPath;
-            }
-        }
-        
-//        measurePath = [[NSBundle mainBundle] pathForResource:@"mus" ofType:@"mpos"];
-//        nodeSourePath = [[NSBundle mainBundle] pathForResource:@"mus" ofType:@"spos"];
-//        xmlFile = [[NSBundle mainBundle] pathForResource:@"Danza_Del_Fuego" ofType:@"xml"];
-//        songPath = [[NSBundle mainBundle] pathForResource:@"Danza_Del_Fuego" ofType:@"mid"];
-        
-        NSDictionary *xmlParm = [KSXMLInfoParse getInfoFromXMLMusicFile:xmlFile];
-        self.nodeArray = [NSMutableArray arrayWithArray:[xmlParm ks_arrayValueForKey:@"noteInfo"]];
-        self.beatType = [self getBeatTypeFromString:[xmlParm ks_stringValueForKey:@"beatType"]];
-        self.manager = [[KYSourceParseManager alloc] init];
-        [self.manager parseMessageSource:measurePath nodeSource:nodeSourePath];
-        
-        [self configAudioSession];
-        // 预加载mid文件
-        [self configPlayerEngineWithSong:songPath];
-        dispatch_main_async_safe(^{
-            [self displayView];
-        });
-        
-    });
-}
-
-- (MetronomeType)getBeatTypeFromString:(NSString *)typeString {
-    if ([typeString isEqualToString:@"1/4"]) {
-        return MetronomeType1V4;
-    }
-    else if ([typeString isEqualToString:@"2/4"]) {
-        return MetronomeType2V4;
-    }
-    else if ([typeString isEqualToString:@"3/4"]) {
-        return MetronomeType3V4;
-    }
-    else if ([typeString isEqualToString:@"4/4"]) {
-        return MetronomeType4V4;
-    }
-    else if ([typeString isEqualToString:@"3/8"]) {
-        return MetronomeType3V8;
-    }
-    else if ([typeString isEqualToString:@"6/8"]) {
-        return MetronomeType6V8;
-    }
-    else {
-        return MetronomeType4V4;
-    }
-}
-
-- (void)configAudioSession {
-    self.audioSessionManager = [[KSAudioSessionManager alloc] init];
-    self.audioSessionManager.delegate = self;
-    [self.audioSessionManager configAudioSession:AUDIOCONFIG_PLAYANDRECORD];
-}
-
-#pragma mark ----- 音频打断相关处理
-
-- (void)handerAudioInterruption {
-    // 处理
-    if (_isEvaluating) { // 如果是评测就停止评测
-        [self cancelEvaluating];
-        // 页面重置
-    }
-    else if (_isPlaying) { // 如果是播放就停止播放
-        [self stopPlayAction];
-    }
-}
-- (void)resumeAudioSession {
-    self.lastPlayNodeIndex = 0;
-    [self.playerEngine resumeAUGraph];
-}
-// 退到后台
-- (void)appEnterBackground {
-    [self handerAudioInterruption];
-}
-
-// 打断处理
-- (void)audioInterruption {
-    if (_videoRecordManager) {
-        [self.videoRecordManager resetSession];
-    }
-    [self handerAudioInterruption];
-}
-
-- (void)stopSession {
-    if (_videoRecordManager) {
-        [self.videoRecordManager stopSession];
-    }
-}
-
-
-#pragma mark ----- socket 相关处理
-
-- (void)connectSocketService {
-    
-    MJWeakSelf;
-    self.socketManager.didReceiveMessage = ^(id  _Nonnull message) {
-        dispatch_async(dispatch_get_main_queue(), ^{
-            // api
-            NSMutableDictionary *sendMessage = [NSMutableDictionary dictionary];
-            [sendMessage setValue:@"sendResult" forKey:@"api"];
-            [sendMessage setValue:message forKey:@"content"];
-            NSLog(@"receive message -----%@",message);
-            // 处理服务端返回的数据
-            NSDictionary *messageDic = [weakSelf convertJsonStringToNSDictionary:message];
-            [weakSelf dealWithMessage:messageDic];
-        });
-    };
-    self.socketManager.connectionStatus = ^(BOOL isSuccess) {
-        dispatch_async(dispatch_get_main_queue(), ^{
-            
-            if (!isSuccess) {
-                NSLog(@"-----连接失败");
-                if (weakSelf.hasSendStartMessage) {
-                    if (weakSelf.AQManager.isRunning) {
-                        [weakSelf cancelEvaluating];
-                        [weakSelf showErrorMessage:@"服务异常,请重试"];
-                        // 处理断连事件
-                        [weakSelf stopRecordService];
-                        weakSelf.isCompareStart = NO;
-                        weakSelf.isSoundCheckStart = NO;
-                    }
-                }
-                else if (weakSelf.evaluatParm) {
-                    // 处理断连事件
-                    [weakSelf cancelEvaluating];
-                    [weakSelf showErrorMessage:@"服务异常,请重试"];
-                    weakSelf.hasSendStartMessage = YES;
-                    weakSelf.isCompareStart = NO;
-                    weakSelf.isSoundCheckStart = NO;
-                }
-                else { // 其他断开
-                    if (weakSelf.AQManager.isRunning) {
-
-                        // 处理断连事件 停止评测
-                        [weakSelf cancelEvaluating];
-                        [weakSelf showErrorMessage:@"服务异常,请重试"];
-                        
-                        [weakSelf stopRecordService];
-                        weakSelf.isCompareStart = NO;
-                        weakSelf.isSoundCheckStart = NO;
-                    }
-                }
-            }
-            else {
-                NSLog(@"-----连接成功");
-                if (weakSelf.hasSendStartMessage == NO && weakSelf.evaluatParm) {
-                    NSDictionary *content = weakSelf.evaluatParm;
-                    NSString *sendData = [weakSelf configDataCommond:@"musicXml" body:content type:@"SOUND_COMPARE"];
-                    [weakSelf sendDataToSocketService:sendData];
-                    [weakSelf showBeatBeforeEvaluating];
-                    weakSelf.hasSendStartMessage = YES;
-                    NSLog(@"---- send musicXML message");
-                }
-            }
-        });
-    };
-    [self.socketManager SRWebSocketOpen];
-}
-
-- (NSDictionary *)convertJsonStringToNSDictionary:(NSString *)jsonString {
-    if (jsonString == nil) {
-        return nil;
-    }
-    NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
-    NSError *error;
-    NSDictionary *json = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
-    if (error) {
-        NSLog(@"jsonString解析失败:%@", error);
-        return nil;
-    }
-    return json;
-}
-
-- (void)sendDataToSocketService:(id)data {
-    if (_socketManager) {
-        [self.socketManager sendData:data];
-    }
-}
-
-// 处理socket返回数据
-- (void)dealWithMessage:(NSDictionary *)messageDic {
-    if (_isEvaluating == NO) { // 非评测状态下不处理
-        return;
-    }
-    NSString *commond = [[messageDic ks_dictionaryValueForKey:@"header"] ks_stringValueForKey:@"commond"];
-    if ([commond isEqualToString:@"measureScore"]) { // 评测返回数据
-        NSDictionary *body = [messageDic ks_dictionaryValueForKey:@"body"];
-        NSInteger score = [body ks_integerValueForKey:@"score"];
-        NSInteger measureIndex = [body ks_integerValueForKey:@"measureIndex"];
-        [self displayScore:score measureIndex:measureIndex];
-    }
-    else if ([commond isEqualToString:@"overall"]) { // 弹窗结果
-        NSDictionary *body = [messageDic ks_dictionaryValueForKey:@"body"];
-        self.recordId = [body ks_integerValueForKey:@"recordId"];
-        NSInteger score = [body ks_integerValueForKey:@"score"];
-        NSInteger intonation = [body ks_integerValueForKey:@"intonation"];
-        NSInteger integrity = [body ks_integerValueForKey:@"integrity"];
-        NSInteger cadence = [body ks_integerValueForKey:@"cadence"];
-        self.resultAlert = [EvaluateResultAlert shareInstance];
-        self.resultAlert.frame = CGRectMake(0, 0, KLandscapeWidth, KLandscapeHeight);
-        [self.resultAlert configWithScore:score intonation:intonation cadence:cadence integrity:integrity];
-        MJWeakSelf;
-        [self.resultAlert resultCallback:^(EVALUATE_RESULT_ACTION action) {
-            [weakSelf resulteAlertAction:action];
-        }];
-        [self.view addSubview:self.resultAlert];
-    }
-    else if ([commond isEqualToString:@"checking"]) { // 校音
-        NSTimeInterval interval = [[NSDate date] timeIntervalSince1970];
-        long long currentMilliseconds = interval * 1000;
-        
-        NSDictionary *body = [messageDic ks_dictionaryValueForKey:@"body"];
-        float frequency = [body ks_doubleValueForKey:@"frequency"];
-        float baseFrequency = [KSXMLInfoParse parsePitchToHZ:self.checkPitch];
-        if (frequency - baseFrequency > 5.0) { // 高了
-            self.correctTimeInterval = 0.0f;
-            [self.checkView showLightDisplay:LIGHTDISPLAY_HIGH];
-        }
-        else if (frequency - baseFrequency < -5.0f) { // 低了
-            self.correctTimeInterval = 0.0f;
-            [self.checkView showLightDisplay:LIGHTDISPLAY_LOW];
-        }
-        else {
-            if (self.correctTimeInterval == 0.0f) {
-                self.correctTimeInterval = currentMilliseconds;
-            }
-            else { // 如果一直持续超过1s
-                long long duration = currentMilliseconds - self.correctTimeInterval;
-                if (duration >= 1000) {
-                    if (self.checkView) {
-                        self.correctTimeInterval = 0.0;
-                        [self.checkView showSuccessCheckEnd];
-                    }
-                }
-            }
-            [self.checkView showLightDisplay:LIGHTDISPLAY_RIGHT];
-        }
-    }
-}
-
-- (NSString *)configDataCommond:(NSString *)commond body:(id)bodyMessage type:(NSString *)dataType {
-    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
-    if (bodyMessage) {
-        [parm setValue:bodyMessage forKey:@"body"];
-    }
-    NSMutableDictionary *headerParm = [NSMutableDictionary dictionary];
-    if ([NSString isEmptyString:commond]) {
-        [headerParm setValue:@"" forKey:@"commond"];
-    }
-    else {
-        [headerParm setValue:commond forKey:@"commond"];
-    }
-    if (![NSString isEmptyString:dataType]) {
-        [headerParm setValue:dataType forKey:@"type"];
-    }
-    [headerParm setValue:@(200) forKey:@"status"];
-    [parm setValue:headerParm forKey:@"header"];
-    return [parm mj_JSONString];
-}
-
-- (void)sendEndMessage {
-    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
-        // 上传停止的信息 发送给服务端
-        NSString *endMessage = @"recordEnd";
-        NSString *endData = [self configDataCommond:endMessage body:nil type:@"SOUND_COMPARE"];
-        [self sendDataToSocketService:endData];
-        self.isCompareStart = NO;
-        NSLog(@"---- send end message");
-    });
-}
-
-
-
-#pragma mark ------ 谱面相关
-// 将displayScroll view 显示的当前音符移动到显示的中间位置
-- (void)moveDisplayViewDisplay {
-    
-    KSParseMessageModel *currentNode = self.manager.nodeMessageArray[self.lastPlayNodeIndex];
-    
-    CGFloat positionY = (currentNode.positionY  + currentNode.elementHeight / 2.0f) / PositionRate * self.scaleRate + currentNode.pageIndex * self.pageViewHeight;
-    CGFloat offsetY = 0.0f;
-    if (positionY < CGRectGetHeight(self.displayScrollView.frame) / 2.0f) {
-        offsetY = 0.0f;
-    }
-    else {
-        offsetY = positionY - CGRectGetHeight(self.displayScrollView.frame) / 2.0f;
-    }
-    [self.displayScrollView setContentOffset:CGPointMake(0, offsetY)];
-}
-
-// 渲染当前小节和评分
-- (void)displayScore:(NSInteger)score measureIndex:(NSInteger)measureIndex {
-    for (KSParseMessageModel *model in self.manager.measureMessageArray) {
-        if (model.elementIndex == measureIndex) {
-            KSMeasureLocationModel *measureLocation = [[KSMeasureLocationModel alloc] init];
-            measureLocation.positionX = model.positionX / PositionRate * self.scaleRate;
-            measureLocation.positionY = model.positionY / PositionRate * self.scaleRate;
-            measureLocation.measureWidth = model.elementWidth / PositionRate * self.scaleRate;
-            measureLocation.measureHeight = model.elementHeight / PositionRate * self.scaleRate;
-            measureLocation.pageIndex = model.pageIndex;
-            
-            measureLocation.fillColor = [self getDisplayColorWithScore:score sourceLocation:measureLocation];
-            
-            NSInteger index = model.pageIndex;
-            StaffImageDisplayView *view = self.pageArray[index];
-            [view addColorView:measureLocation];
-            break;
-        }
-    }
-}
-
-- (UIColor *)getDisplayColorWithScore:(NSInteger)score sourceLocation:(KSMeasureLocationModel *)model {
-    UIColor *measureBgColor;
-    UIColor *titleColor;
-    NSString *imageName = @"";
-    
-    if (score >= 90) { // perfect
-        measureBgColor = HexRGBAlpha(0xffd4c0, 0.47f);
-        
-        titleColor = HexRGB(0x516AFF);
-        imageName = @"score_perfect";
-    }
-    else if (score >= 70) { // great
-        measureBgColor = HexRGBAlpha(0xffb252, 0.48f);
-        titleColor = HexRGB(0xFF8E5A);
-        imageName = @"score_great";
-    }
-    else if (score >= 40) { // good
-        measureBgColor = HexRGBAlpha(0x2dc7aa, 0.17f);
-        titleColor = HexRGB(0xFF958B);
-        imageName = @"score_good";
-    }
-    else { // bad
-        measureBgColor = HexRGBAlpha(0xff8e8e, 0.32f);
-        titleColor = HexRGB(0xEE4C6A);
-        imageName = @"score_bad";
-    }
-    CGFloat viewHeight = 40.0f;
-    CGRect viewFrame = CGRectMake(model.positionX, model.positionY+viewHeight, model.measureWidth, viewHeight);
-    [self showScoreViewInPage:model.pageIndex frame:viewFrame titleColor:titleColor score:score imageName:imageName];
-    
-    return measureBgColor;
-}
-
-- (void)showScoreViewInPage:(NSInteger)pageIndex frame:(CGRect)frame titleColor:(UIColor *)titleColor score:(NSInteger)score imageName:(NSString *)imageName {
-    CGFloat distanceY = 20.0f;
-    ScoreAnimationView *view = [[ScoreAnimationView alloc] initWithFrame:frame animitionDistance:distanceY score:score titleColor:titleColor imageName:imageName];
-    
-    StaffImageDisplayView *pageView = self.pageArray[pageIndex];
-    [view showInView:pageView];
-}
-
-
-#pragma mark ------ 评测结果处理
-- (void)showReportView {
-
-    KSBaseWKWebViewController *reportCtrl = [[KSBaseWKWebViewController alloc] init];
-    reportCtrl.url = [NSString stringWithFormat:@"%@/accompany/#/report/%zd",WEBHOST,self.recordId];
-    self.keepOrientation = YES;
-    reportCtrl.keepOrientation = YES;
-    [self.navigationController pushViewController:reportCtrl animated:YES];
-}
-
-- (void)resulteAlertAction:(EVALUATE_RESULT_ACTION)action {
-    switch (action) {
-        case EVALUATE_RESULT_ACTION_CANCLE: // 退出评测模式
-        {
-            [self.resultAlert removeFromSuperview];
-            [self quitEvaluatingMode];
-        }
-            break;
-        case EVALUATE_RESULT_ACTION_SHARE:  // 分享
-        {
-            // share function
-            
-        }
-            break;
-        case EVALUATE_RESULT_ACTION_SUBMIT: // 上传到云端
-        {
-            if (self.cameraOn && self.saveVideo) { // 上传视频到云端
-                [self videoUpdate];
-            }
-            else { // 直接发送消息显示音频
-                [self sendUploadMessage:nil];
-            }
-        }
-            break;
-        case EVALUATE_RESULT_ACTION_PRACTICE:  // 练习
-        {
-            [self.resultAlert removeFromSuperview];
-            [self quitEvaluatingMode];
-        }
-            break;
-        case EVALUATE_RESULT_ACTION_TAYAGAIN:  // 再试一次
-        {
-            [self.resultAlert removeFromSuperview];
-            [self clearAllColorDisplayView];
-        }
-            break;
-        case EVALUATE_RESULT_ACTION_REPORT:   // 报告
-        {
-            [self showReportView];
-        }
-            break;
-        default:
-            break;
-    }
-}
-
-#pragma mark ------ recorder
-// 初始化录制引擎
-- (void)configRecordManager {
-    if (self.AQManager.isRunning) {
-        [self.AQManager stopRecord];
-    }
-    self.AQManager = [[KSAQRecordManager alloc] init];
-    self.AQManager.delegate = self;
-}
-// 开始录制
-- (void)startRecordService {
-    if (self.AQManager.isRunning) {
-        [self.AQManager stopRecord];
-    }
-    [self.AQManager startRecord];
-}
-// 停止录制
-- (void)stopRecordService {
-    if (self.AQManager.isRunning) {
-        [self.AQManager stopRecord];
-    }
-}
-
-
-#pragma mark-------- KSAQRecordManagerDelegate
-- (void)recordInterruption {
-
-    [self cancelEvaluating];
-    [self showErrorMessage:@"录制错误,请重试"];
-}
-
-- (void)audioRouteChange:(AUDIODEVICE_TYPE)type {
-    NSString *valueStr = @"";
-    BOOL checkIsWired = NO;
-    switch (type) {
-        case AUDIODEVICE_TYPE_HEADPHONE:
-        {
-            valueStr = @"有线耳机";
-            checkIsWired = YES;
-        }
-            break;
-        case AUDIODEVICE_TYPE_BLUETOOTH:
-        {
-            valueStr = @"蓝牙耳机";
-            checkIsWired = YES;
-        }
-            break;
-        case AUDIODEVICE_TYPE_NONE:
-        {
-            valueStr = @"";
-            checkIsWired = NO;
-        }
-            break;
-        default:
-            break;
-    }
-    
-    if (checkIsWired == NO) {
-        [self showNoWiredTipsAlertCallback:^{
-            
-        }];
-    }
-
-}
-
-- (void)audioRecord:(KSAQRecordManager *)audioRecord didRecordAudioData:(void *)data length:(UInt32)length {
-    
-    if (self.socketManager.socketReadyState != SR_OPEN) {
-        return;
-    }
-    NSData *pushData = [[NSData alloc] initWithBytes:data length:length];
-    if (self.isCompareStart) { // 发送评测开始消息
-        NSLog(@"--------- send start message");
-        _isCompareStart = NO;
-        NSString *startMessage = @"recordStart";
-        NSString *startString = [self configDataCommond:startMessage body:nil type:@"SOUND_COMPARE"];
-        [self sendDataToSocketService:startString];
-    }
-    else if (self.isSoundCheckStart) { // 校音开始
-        
-        NSLog(@"--------- send check start message");
-        _isSoundCheckStart = NO;
-        NSString *checkStartMessage = @"start";
-        NSString *startString = [self configDataCommond:checkStartMessage body:nil type:@"PITCH_DETECTION"];
-        [self sendDataToSocketService:startString];
-    }
-    [self sendDataToSocketService:pushData];
-}
-
-
-#pragma mark ---  player 播放引擎 播放和停止播放UI
-// 初始化播放引擎
-- (void)configPlayerEngineWithSong:(NSString *)songPath {
-    [LOADING_MANAGER showHUD];
-    self.playerEngine = [[MidiPlayerEngine alloc] init];
-    self.playerEngine.accompanyVolume = 0.3f;
-    self.playerEngine.reportTime = 10;
-    self.playerEngine.delegate = self;
-    [self.playerEngine configSoundFilePath:[[NSBundle mainBundle]
-                                            pathForResource:@"synthgms" ofType:@"sf2"]];
-    // 获取当前主声部对应的乐器id
-    self.playerEngine.instrumentId = 73;
-    [self.playerEngine loadMIDIFileWithString:songPath];
-    
-    
-    NSLog(@"--------- instanment track --- %d", self.playerEngine.baseInstrumentTrack);
-//    [self.playerEngine volumeOtherTrackExcept:self.playerEngine.baseInstrumentTrack withVolume:0];
-    if (self.currentSpeed == 0) {
-        self.currentSpeed = self.playerEngine.baseRate;
-    }
-    dispatch_async(dispatch_get_main_queue(), ^{
-        [LOADING_MANAGER MBShowAUTOHidingInWindow:@"加载完成"];
-        [LOADING_MANAGER removeHUD];
-        CloudControlButton *speedButton = [self.headView viewWithTag:BUTTON_TAG_SPEED];
-        [speedButton showSpeed:self.currentSpeed];
-    });
-}
-
-/* 播放时,显示光标 曲谱不可手动滑动,根据播放进度自动移动位置
-   停止播放时,隐藏光标,光标回到初始位置,曲谱滑动禁用关闭。
- */
-- (void)playAction {  // 播放
-    CloudControlButton *playButton = [self.headView viewWithTag:BUTTON_TAG_PLAY];
-    playButton.isSelected = YES;
-    self.isPlaying = YES;
-    self.displayScrollView.scrollEnabled = NO;
-    [self showCursor];
-    if ([self.playerEngine isPlayingFile]) {
-        [self.playerEngine stopPlayingMIDIFile];
-    }
-    
-    // 将displayScroll view 显示的当前音符移动到显示的中间位置
-    [self moveDisplayViewDisplay];
-    
-    if (self.startMeasure != -1) {
-
-        [self.playerEngine setProgressTime:self.playerEngine.startTime];
-        [self.playerEngine playMIDIFile];
-    }
-    else {
-        [self.playerEngine playMIDIFile];
-    }
-}
-
-- (void)stopPlayAction { // 停止播放
-    self.isPlaying = NO;
-    [self hideCursor];
-    self.displayScrollView.scrollEnabled = YES;
-    if ([self.playerEngine isPlayingFile]) {
-        [self.playerEngine stopPlayingMIDIFile];
-    }
-    CloudControlButton *playButton = [self.headView viewWithTag:BUTTON_TAG_PLAY];
-    playButton.isSelected = NO;
-}
-
-#pragma mark ---- PlayerEngineDelegate
-- (void)ProgressUpdated:(float)progress currentTime:(MusicTimeStamp)currentTime {
-    
-    // 如果是最后一个节点
-    if (self.lastPlayNodeIndex == self.manager.nodeMessageArray.count - 1) {
-        return;
-    }
-    KSParseMessageModel *nextNode = self.manager.nodeMessageArray[self.lastPlayNodeIndex+1];
-    if (nextNode.elementTimePosition <= currentTime*1000) {
-        KSParseMessageModel *currentNode = self.manager.nodeMessageArray[self.lastPlayNodeIndex];
-        
-        self.lastPlayNodeIndex +=1;
-        [self moveCursorViewWithNode:nextNode];
-        // 如果换行或者到下一页
-        if (currentNode.positionY < nextNode.positionY || currentNode.pageIndex < nextNode.pageIndex) {
-            [self moveDisplayViewDisplay];
-        }
-    }
-}
-    
-- (void)playEnd {
-    // 判断是否需要重播
-    if (_isNeedRepeat && _isPlaying && _isEvaluating == NO) {
-        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
-            [self stopPlayAction];
-            self.lastPlayNodeIndex = 0;
-            [self showBeatBeforePlay];
-        });
-    }
-    else {
-        if (_isEvaluating) { // 如果在评测状态下
-            [self endEvaluating];
-        }
-        [self resetPlayButtonStatus];
-    }
-}
-
-- (void)resetPlayButtonStatus {
-    [self.playerEngine setProgressTime:0.0f];
-    CloudControlButton *playButton = [self.headView viewWithTag:BUTTON_TAG_PLAY];
-    playButton.isSelected = NO;
-    self.lastPlayNodeIndex = 0;
-    [self hideCursor];
-    self.displayScrollView.scrollEnabled = YES;
-}
-
-
-- (void)GetMusicTotalTime:(float)time {
-    
-}
-
-
-- (void)quitEvaluatingMode {
-    self.isEvaluating = NO;
-    [self clearAllColorDisplayView];
-    CloudControlButton *evaluateButton = [self.headView viewWithTag:BUTTON_TAG_EVALUATING];
-    evaluateButton.isSelected = NO;
-}
-
-
-- (void)showErrorMessage:(NSString *)message {
-    [LOADING_MANAGER MBShowAUTOHidingInWindow:message];
-}
-
-
-- (void)displayView {
-    [self.view addSubview:self.viewContainer];
-    _backView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KLandscapeWidth, KLandscapeHeight)];
-    _backView.backgroundColor = THEMECOLOR;
-    [self.view addSubview:_backView];
-    _bgColorView = [[UIView alloc] initWithFrame:self.defaultFrame];
-    _bgColorView.layer.cornerRadius = 14.0f;
-    [self.backView addSubview:_bgColorView];
-    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
-        if (self.cameraOn) {
-            self.backView.alpha = BACKVIEW_ALPHA;
-            [self.videoRecordManager configSessiondisplayInView:self.viewContainer];
-        }
-    });
-    _headView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KLandscapeWidth, 78)];
-    _headView.backgroundColor = [UIColor clearColor];
-    [self.backView addSubview:_headView];
-    // 配置顶部按钮
-    [self configButtonInView:_headView];
-    
-    // 创建右侧帮助按钮
-    [self createHelpButton];
-
-    // 创建scorll view 容器添加图片
-    [self createDisplayScrollView];
-}
-
-
-
-- (void)createHelpButton {
-    self.helpButton = [UIButton buttonWithType:UIButtonTypeCustom];
-    self.helpButton.frame = CGRectMake(KLandscapeWidth - 46, (KLandscapeHeight - 86) /2.0f, 46, 86);
-    [self.helpButton setImage:[UIImage imageNamed:@"cloud_help"] forState:UIControlStateNormal];
-    [self.helpButton addTarget:self action:@selector(helpAction) forControlEvents:UIControlEventTouchUpInside];
-    [self.view addSubview:self.helpButton];
-}
-
-- (void)helpAction {
-    CloudHelpView *helpView = [CloudHelpView shareInstance];
-    helpView.frame = CGRectMake(0, 0, KLandscapeWidth, KLandscapeHeight);
-    MJWeakSelf;
-    [helpView feedbackCallback:^{
-        [weakSelf showFeedbackUI];
-    }];
-    [self.view addSubview:helpView];
-}
-
-- (void)showFeedbackUI {
-    MJWeakSelf;
-    self.feedbackView = [CloudFeedbackView shareInstance];
-    self.feedbackView.frame = CGRectMake(0, 0, KLandscapeWidth, KLandscapeHeight);
-    [self.feedbackView submitCallback:^(NSString * _Nonnull content, NSString * _Nonnull type) {
-        [weakSelf submitFeedbackAction:content type:type];
-    }];
-    [self.view addSubview:self.feedbackView];
-}
-
-- (void)submitFeedbackAction:(NSString *)content type:(NSString *)type {
-    [LOADING_MANAGER showHUD];
-    [KSNetworkingManager cloudFeedbackRequest:KS_POST content:content type:type success:^(NSDictionary * _Nonnull dic) {
-        [LOADING_MANAGER removeHUD];
-        if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
-            [LOADING_MANAGER MBShowAUTOHidingInWindow:@"反馈成功"];
-            [self.feedbackView removeFromSuperview];
-        }
-        else {
-            [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
-        }
-    } faliure:^(NSError * _Nonnull error) {
-        [LOADING_MANAGER removeHUD];
-    }];
-}
-
-- (void)createDisplayScrollView {
-    [self.pageArray removeAllObjects];
-    if (self.needShowFinger) {
-        self.displayScrollView.frame = CGRectMake(0, 0, CGRectGetWidth(self.resizeFrame), CGRectGetHeight(self.resizeFrame));
-    }
-    else {
-        self.displayScrollView.frame = CGRectMake(0, 0, CGRectGetWidth(self.defaultFrame), CGRectGetHeight(self.defaultFrame));
-    }
-    [self.bgColorView addSubview:self.displayScrollView];
-    // 获取当前文件夹中所有图片
-    NSMutableArray *imgArray = [NSMutableArray array];
-    for (NSString *filePath in self.zipFileArray) {
-        if ([filePath containsString:@".png"]) {
-            [imgArray addObject:filePath];
-        }
-    }
-    
-//    NSLog(@"%@", imgArray.description);
-//    for (int i = 1; i < 6; i++) {
-//        NSString *name = [NSString stringWithFormat:@"mus-%d",i];
-//        [imgArray addObject:[[NSBundle mainBundle] pathForResource:name ofType:@"png"]];
-//    }
-    
-    
-
-    UIImage *img = [UIImage imageNamed:imgArray[0]];
-    CGFloat width = img.size.width;
-    CGFloat height = img.size.height;
-    CGFloat displayWidth = CGRectGetWidth(self.displayScrollView.frame);
-    
-    self.scaleRate = displayWidth / width;
-    CGFloat viewHeight = self.scaleRate * height;
-    self.pageViewHeight = viewHeight;
-    
-    self.bgColorType = self.eyeShieldOn ? COLOR_DISPLAYTYPE_PROTECT : COLOR_DISPLAYTYPE_NOMAL;
-    
-    for (NSInteger i = 0; i < imgArray.count; i++) { // 创建 StaffImageDisplayView
-        
-        StaffImageDisplayView *displayView = [[StaffImageDisplayView alloc] initWithImage:imgArray[i] pageIndex:i frame:CGRectMake(0, i * viewHeight, displayWidth, viewHeight)];
-        displayView.tag = 1000 + i;
-        MJWeakSelf;
-        [displayView viewTapActionCallback:^(CGFloat positionX, CGFloat positionY, NSInteger pageIndex) {
-            [weakSelf dealWithPositionX:positionX positionY:positionY pageIndex:pageIndex];
-        }];
-        [self.pageArray addObject:displayView];
-        [self.displayScrollView addSubview:displayView];
-    }
-    CGFloat contentHeight = viewHeight * imgArray.count;
-    if (contentHeight < self.displayScrollView.bounds.size.height) {
-        contentHeight = self.displayScrollView.bounds.size.height;
-    }
-    self.displayScrollView.contentSize = CGSizeMake(displayWidth, contentHeight);
-    
-    if (self.needShowFinger) {
-        [self.bgColorView addSubview:self.fingerDisplayView];
-    }
-    if (self.isPlaying) {
-        self.displayScrollView.scrollEnabled = NO;
-        [self.displayScrollView addSubview:self.cursorView];
-    }
-    else {
-        self.displayScrollView.scrollEnabled = YES;
-    }
-}
-
-
-
-- (void)configButtonInView:(UIView *)displayView {
-    UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
-    backButton.frame = CGRectMake(21, 19, 32, 32);
-    backButton.layer.cornerRadius = 16.0f;
-    [backButton setImage:[UIImage imageNamed:@"cloud_back"] forState:UIControlStateNormal];
-    [backButton setTitleColor:HexRGB(0x000000) forState:UIControlStateNormal];
-    backButton.backgroundColor = [UIColor whiteColor];
-    [backButton addTarget:self action:@selector(backAction) forControlEvents:UIControlEventTouchUpInside];
-    [displayView addSubview:backButton];
-    
-    if (![NSString isEmptyString:self.songName]) {
-        UIView *songNameView = [[UIView alloc] initWithFrame:CGRectMake(70, 17, 180, 40)];
-        songNameView.backgroundColor = [UIColor whiteColor];
-        songNameView.layer.cornerRadius = 20.0f;
-        [displayView addSubview:songNameView];
-        
-        UIImageView *logoImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"cloudSong_logo"]];
-        logoImage.frame = CGRectMake(7, 5, 28, 28);
-        [songNameView addSubview:logoImage];
-        
-        UIImageView *nextImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"cloudSong_next"]];
-        nextImage.frame = CGRectMake(CGRectGetWidth(songNameView.frame) - 9 - 14, 14, 9, 12);
-        [songNameView addSubview:nextImage];
-        
-        UILabel *songLabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(logoImage.frame) + 6, 0, CGRectGetMinX(nextImage.frame) - 5 - CGRectGetMaxX(logoImage.frame) - 6, 40)];
-        songLabel.textAlignment = NSTextAlignmentLeft;
-        songLabel.textColor = HexRGB(0x000000);
-        songLabel.font = [UIFont systemFontOfSize:16.0f weight:UIFontWeightMedium];
-        songLabel.text = self.songName;
-        [songNameView addSubview:songLabel];
-    }
-    
-    NSArray *imageArray = @[@"evaluate_nomal",@"select_normal",@"play_play",@"switch_nomal",@"cloud_playback",@"cloud_speed",@"cloud_setting"];
-    NSArray *selectImageArray = @[@"evaluate_selected",@"select_choose",@"play_pause",@"switch_accompany",@"cloud_playback",@"cloud_speed",@"cloud_setting"];
-    NSArray *titleArray = @[@"评测",@"选段",@"播放",@"原声",@"重播",@"速度",@"设置"];
-    NSArray *selectTitleArray = @[@"评测",@"选段",@"暂停",@"伴奏",@"重播",@"速度",@"设置"];
-    
-    for (NSInteger i = imageArray.count - 1; i >= 0; i--) {
-        CGRect frame = CGRectMake((KLandscapeWidth - 46) - (imageArray.count - i) * Button_Width - (imageArray.count - 1 - i)*Button_Space, 9, 34, 60);
-        MJWeakSelf;
-        CloudControlButton *button = [CloudControlButton createButtonWithImage:imageArray[i] selectImage:selectImageArray[i] buttonTitle:titleArray[i] selectTitle:selectTitleArray[i] tag:1000+i frame:frame callback:^(CloudControlButton * _Nonnull sender, BOOL isSelected) {
-            [weakSelf buttonClickAction:sender isSelected:isSelected];
-        }];
-        if (i == 5 && self.currentSpeed != 0) {
-            [button showSpeed:self.currentSpeed];
-        }
-        [displayView addSubview:button];
-    }
-}
-
-- (void)buttonClickAction:(CloudControlButton *)sender isSelected:(BOOL)isSelected {
-    BUTTON_TAG type = sender.tag;
-    switch (type) {
-        case BUTTON_TAG_EVALUATING:  // 评测开关
-        {
-            if (isSelected) { // 开启时设置其他按钮禁用 重新布局曲谱页面
-                self.isEvaluating = YES;
-                
-                MJWeakSelf;
-                [self checkIsWiredHeadsetOnCallback:^{
-                    if (weakSelf.soundCheckOn && ![weakSelf.songMessageSource.subjectId isEqualToString:@"23"]) { // 如果是打击乐跳过
-                        [weakSelf startSoundCheck];
-                    }
-                }];
-            }
-            else { // 恢复按钮 重新恢复曲谱布局
-                self.isEvaluating = NO;
-            }
-        }
-            break;
-        case BUTTON_TAG_SELECT:
-        {
-            if (isSelected) {
-                self.isChooseMeasure = YES;
-            }
-            else {
-                [self stopPlayAction];
-                self.isChooseMeasure = NO;
-                // 清理全部
-                self.startMeasure = -1;
-                self.endMeasure = -1;
-                self.lastPlayNodeIndex = 0;
-                self.playerEngine.startTime = 0.0f;
-                self.playerEngine.endTime = 0.0f;
-                [self.playerEngine setProgressTime:self.playerEngine.startTime];
-                [self clearAllColorDisplayView];
-            }
-        }
-            break;
-        case BUTTON_TAG_PLAY:
-        {
-            if (isSelected) { // 播放
-
-                CGFloat rate = self.currentSpeed / self.playerEngine.baseRate;
-                [self.playerEngine setMusicPlayerSpeed:rate];
-                [self showBeatBeforePlay];
-            }
-            else { // 暂停
-                [self stopPlayAction];
-            }
-            
-        }
-            break;
-        case BUTTON_TAG_SWITCH:
-        {
-            [self.trackChooseView showInView:self.view];
-//            if (isSelected) { // 切换成伴奏
-//                [self.playerEngine muteTrack:YES WithTrack:self.playerEngine.baseInstrumentArray];
-//            }
-//            else { // 切换成原声
-//                [self.playerEngine muteTrack:NO WithTrack:self.playerEngine.baseInstrumentArray];
-//            }
-
-        }
-            break;
-        case BUTTON_TAG_REPEAT: // 从头开始播放
-        {
-            [self.playerEngine setProgressTime:0.0f];
-            [self displayCourseToFirstNode];
-            CloudControlButton *playButton = [self.headView viewWithTag:BUTTON_TAG_PLAY];
-            playButton.isSelected = YES;
-            [self showBeatBeforePlay];
-        }
-            break;
-        case BUTTON_TAG_SPEED: // 调速
-        {
-            // 显示调速控件
-            [self showSpeedView];
-        }
-            break;
-        case BUTTON_TAG_SETTING: // 设置
-        {
-            [self showSettingView];
-        }
-            break;
-        default:
-            break;
-    }
-}
-
-- (void)showSpeedView {
-    LFPopupMenu *popView = [[LFPopupMenu alloc] init];
-    popView.needBorder = YES;
-    popView.minWidth = 80;
-    [popView configWithCustomView:self.sliderView];
-    
-    CloudControlButton *playButton = [self.headView viewWithTag:BUTTON_TAG_SPEED];
-    [popView showArrowToView:playButton];
-}
-
-- (void)showSettingView {
-    KSCloudSettingView *settingView = [KSCloudSettingView shareInstance];
-    settingView.frame = CGRectMake(0, 0, KLandscapeWidth, KLandscapeHeight);
-    // 设置回调
-    MJWeakSelf;
-    [settingView settingCallback:^(CLOUDSETTING_TYPE type, BOOL isOn, NSString * _Nonnull level) {
-        [weakSelf configViewDisplayType:type isOn:isOn level:level];
-    }];
-    [self.view addSubview:settingView];
-}
-
-- (void)setBgColorType:(COLOR_DISPLAYTYPE)bgColorType {
-    _bgColorType = bgColorType;
-    if (bgColorType == COLOR_DISPLAYTYPE_PROTECT) {
-        self.bgColorView.backgroundColor = HexRGB(0xfff4e1);
-    }
-    else {
-        self.bgColorView.backgroundColor = [UIColor whiteColor];
-    }
-}
-
-
-- (void)configViewDisplayType:(CLOUDSETTING_TYPE)type isOn:(BOOL)isOn level:(NSString *)level {
-    switch (type) {
-        case CLOUDSETTING_TYPE_EYESHIELD: // 护眼模式
-        {
-            self.eyeShieldOn = isOn;
-            self.bgColorType = isOn ? COLOR_DISPLAYTYPE_PROTECT : COLOR_DISPLAYTYPE_NOMAL;
-        }
-            break;
-        case CLOUDSETTING_TYPE_SOUNDCHECK:
-        {
-            self.soundCheckOn = isOn;
-        }
-            break;
-        case CLOUDSETTING_TYPE_CAMERA:
-        {
-            self.backView.alpha = isOn ? BACKVIEW_ALPHA : 1.0f;
-            self.cameraOn = isOn;
-            [self openCamera:isOn];
-        }
-            break;
-        case CLOUDSETTING_TYPE_REPEAT:
-        {
-            self.isNeedRepeat = isOn;
-        }
-            break;
-        case CLOUDSETTING_TYPE_FINGER:
-        {
-            self.showFinger = isOn;
-            // 刷新页面布局
-            [self displayFingerView];
-        }
-            break;
-        case CLOUDSETTING_TYPE_LEVEL:
-        {
-            self.level = level;
-        }
-            break;
-        case CLOUDSETTING_TYPE_SAVEVIDEO:
-        {
-            self.saveVideo = isOn;
-        }
-            break;
-        case CLOUDSETTING_TYPE_ACCOMPANY:
-        {
-            self.accompanyOn = isOn;
-        }
-            break;
-        default:
-            break;
-    }
-}
-
-- (void)displayFingerView {
-    if (self.needShowFinger) {
-        [self.displayScrollView removeFromSuperview];
-        _displayScrollView = nil;
-        [self createDisplayScrollView];
-    }
-    else {
-        [self.fingerDisplayView removeFromSuperview];
-        [self.displayScrollView removeFromSuperview];
-        _displayScrollView = nil;
-        [self createDisplayScrollView];
-    }
-}
-
-- (void)openCamera:(BOOL)isOpen {
-    if (isOpen) { // 开启摄像头
-        PREMISSIONTYPE canOpenCamera = [RecordCheckManager checkCameraPremissionAvaiable];
-        if (canOpenCamera == PREMISSIONTYPE_YES) {
-            [self.videoRecordManager configSessiondisplayInView:self.viewContainer];
-        }
-    }
-    else {
-        if (self->_videoRecordManager) {
-            [self.videoRecordManager removeDisplay];
-        }
-    }
-}
-
-- (void)dealWithPositionX:(CGFloat)positionX positionY:(CGFloat)positionY pageIndex:(NSInteger)pageIndex {
-    //  如果不是选段模式 不计算
-    if (!self.isChooseMeasure) {
-        return;
-    }
-    
-    // 找到当前选择的小节
-    // 获取当前图片上对应的x,y所对应的位置文件中的 点
-    CGFloat locationX = positionX / self.scaleRate * PositionRate;
-    CGFloat locationY = positionY / self.scaleRate * PositionRate;
-    
-    for (KSParseMessageModel *model in self.manager.measureMessageArray) {
-        
-        if (model.pageIndex == pageIndex) { // 先找到当前的page数据
-            // 判断是否落在小节X轴范围区间
-            BOOL isLocationInX = (model.positionX < locationX && (model.positionX + model.elementWidth) >= locationX);
-            // 判断是否落在小节Y轴范围区间
-            BOOL isLocationInY = (model.positionY < locationY && (model.positionY + model.elementHeight) >= locationY);
-            if (isLocationInX && isLocationInY) { // 认为当前小节是被选中小节
-                NSInteger chooseMeasure = model.elementIndex;
-                [self evaluateChooseMeasure:chooseMeasure];
-                break;
-            }
-        }
-    }
-}
-
-- (void)evaluateChooseMeasure:(NSInteger)chooseMeasure {
-    if (self.startMeasure == -1 && self.endMeasure == -1) {
-        self.startMeasure = chooseMeasure;
-        self.endMeasure = chooseMeasure;
-    }
-    if (self.startMeasure > chooseMeasure) {
-        self.startMeasure = chooseMeasure;
-    }
-    else if (self.startMeasure < chooseMeasure) {
-        self.endMeasure = chooseMeasure;
-    }
-    // 获取选段时间
-    NSInteger index = self.startMeasure;
-    BOOL chooseEndMeasure = NO;
-    if (self.endMeasure == self.manager.measureMessageArray.count-1) {
-        chooseEndMeasure = YES;
-    }
-    NSInteger endIndex = chooseEndMeasure ? self.endMeasure : self.endMeasure+1;
-    // 1.根据小节找到小节开始的时值
-    for (KSParseMessageModel *model in self.manager.measureMessageArray) {
-        if (index == model.elementIndex) {
-            self.playerEngine.startTime = model.elementTimePosition / 1000;
-        }
-        else if (chooseEndMeasure) { // 如果结束是最后一小节
-            self.playerEngine.endTime = 0.0f;
-        }
-        // 如果不是最后一个小节
-        else if (!chooseEndMeasure && endIndex == model.elementIndex) {
-            self.playerEngine.endTime = model.elementTimePosition / 1000;
-        }
-    }
-    
-    // 重新绘制layer颜色
-    NSMutableArray *colorViewArray = [NSMutableArray array];
-    
-    for (KSParseMessageModel *model in self.manager.measureMessageArray) {
-        if (model.elementIndex >= self.startMeasure && model.elementIndex <= self.endMeasure) {
-            
-            KSMeasureLocationModel *measureLocation = [[KSMeasureLocationModel alloc] init];
-            measureLocation.positionX = model.positionX / PositionRate * self.scaleRate;
-            measureLocation.positionY = model.positionY / PositionRate * self.scaleRate;
-            measureLocation.measureWidth = model.elementWidth / PositionRate * self.scaleRate;
-            measureLocation.measureHeight = model.elementHeight / PositionRate * self.scaleRate;
-            measureLocation.pageIndex = model.pageIndex;
-            measureLocation.fillColor = HexRGB(0xffe7bd);
-            [colorViewArray addObject:measureLocation];
-        }
-    }
-    // 先清除全部color
-    [self clearAllColorDisplayView];
-    // 添加
-    for (KSMeasureLocationModel *model in colorViewArray) {
-        NSInteger index = model.pageIndex;
-        StaffImageDisplayView *view = self.pageArray[index];
-        [view addColorView:model];
-    }
-}
-
-- (void)clearAllColorDisplayView {
-    
-    for (StaffImageDisplayView *view in self.pageArray) {
-        [view clearAllColorView];
-    }
-}
-
-- (NSMutableArray *)getAllImageFile:(NSString *)path {
-    NSMutableArray *filePathArray = [NSMutableArray array];
-    NSFileManager *fileManger = [NSFileManager defaultManager];
-    BOOL isDir = NO;
-    BOOL isExist = [fileManger fileExistsAtPath:path isDirectory:&isDir];
-    if (isExist) {
-        if (isDir) {
-            NSArray * dirArray = [fileManger contentsOfDirectoryAtPath:path error:nil];
-            NSString * subPath = nil;
-            for (NSString * str in dirArray) {
-                subPath  = [path stringByAppendingPathComponent:str];
-                BOOL issubDir = NO;
-                [fileManger fileExistsAtPath:subPath isDirectory:&issubDir];
-                [self getAllImageFile:subPath];
-            }
-        }else{
-            NSString *fileName = [path getUrlFileName];
-            if ([fileName hasSuffix:@".png"]) {
-                //do anything you want
-                [filePathArray addObject:path];
-            }
-        }
-    }else{
-        NSLog(@"this path is not exist!");
-    }
-    return filePathArray;
-}
-
-- (void)backAction {
-    [self dismissViewControllerAnimated:YES completion:nil];
-}
-
-
-- (void)showFingerView {
-    
-    if (self.needShowFinger && self.fingerImageDic != nil) {
-        
-        NSMutableDictionary *parm  = self.nodeArray[self.lastPlayNodeIndex];
-        NSInteger noteValue = [parm ks_integerValueForKey:@"note_value"];
-
-        NSArray *noteFingerArray = [self.fingerImageDic ks_arrayValueForKey:[NSString stringWithFormat:@"%zd",noteValue]];
-        // 剔除
-        [self.fingerContentView removeAllSubViews];
-        
-        if (noteFingerArray.count) {
-            NSString *imgStr = [noteFingerArray firstObject];
-            NSArray *imgArray = [imgStr componentsSeparatedByString:@","];
-            
-            for (NSString *imgName in imgArray) {
-                UIImageView *fingerView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.fingerContentView.frame), CGRectGetHeight(self.fingerContentView.frame))];
-                [fingerView setImage:[UIImage imageNamed:imgName]];
-                [self.fingerContentView addSubview:fingerView];
-            }
-        }
-    }
-}
-
-
-- (void)showCursor {  // 显示光标
-    // 获取当前播放位置
-    [self.displayScrollView addSubview:self.cursorView];
-    if (self.startMeasure == -1) {
-        if (self.lastPlayNodeIndex == 0) {
-            [self displayCourseToFirstNode];
-        }
-    }
-    else {  // 获取当前选择小节
-        
-        NSInteger index = self.startMeasure;
-        Float64 timePosition = 0;
-        
-        // 1.根据小节找到小节开始的时值
-        for (KSParseMessageModel *model in self.manager.measureMessageArray) {
-            if (index == model.elementIndex) {
-                timePosition = model.elementTimePosition;
-                break;
-            }
-        }
-        // 2.根据时值获取对应音符位置
-        for (KSParseMessageModel *nodeModel in self.manager.nodeMessageArray) {
-            
-            if (nodeModel.elementTimePosition == timePosition) {
-                
-                [self moveCursorViewWithNode:nodeModel];
-                break;
-            }
-        }
-    }
-    self.cursorView.hidden = NO;
-}
-
-- (void)hideCursor {  // 隐藏光标
-    // 重置播放位置
-    self.cursorView.hidden = YES;
-    [self.cursorView removeFromSuperview];
-}
-
-- (void)displayCourseToFirstNode {
-    // 获取第一个音符位置
-    KSParseMessageModel *firstNode = self.manager.nodeMessageArray[0];
-    [self moveCursorViewWithNode:firstNode];
-}
-
-- (void)moveCursorViewWithNode:(KSParseMessageModel *)nodeModel {
-    self.lastPlayNodeIndex = nodeModel.elementIndex;
-    CGFloat positionX = nodeModel.positionX / PositionRate * self.scaleRate;
-    CGFloat positionY = nodeModel.positionY / PositionRate * self.scaleRate + self.pageViewHeight*(nodeModel.pageIndex);
-    CGFloat cursorWidth = nodeModel.elementWidth / PositionRate * self.scaleRate;
-    CGFloat cursorHeight = nodeModel.elementHeight / PositionRate * self.scaleRate;
-    self.cursorView.frame = CGRectMake(positionX, positionY, cursorWidth, cursorHeight);
-    
-    // 指法同步
-    [self showFingerView];
-}
-
-
-
-#pragma mark -------- lazying
-- (CGRect)defaultFrame {
-    return CGRectMake(Left_Space, 78, KLandscapeWidth - Left_Space*2, KLandscapeHeight - 78 - 10);
-}
-- (UIView *)cursorView {
-    if (!_cursorView) {
-        _cursorView = [[UIView alloc] initWithFrame:CGRectZero];
-        _cursorView.hidden = YES;
-        _cursorView.backgroundColor = HexRGBAlpha(0xff5a25, 0.4f);
-    }
-    return _cursorView;
-}
-- (UIScrollView *)displayScrollView {
-    if (!_displayScrollView) {
-        _displayScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.defaultFrame), CGRectGetHeight(self.defaultFrame))];
-        _displayScrollView.backgroundColor = [UIColor clearColor];
-        _displayScrollView.scrollEnabled = YES;
-        _displayScrollView.showsHorizontalScrollIndicator = NO;
-        _displayScrollView.showsVerticalScrollIndicator = NO;
-        _displayScrollView.bounces = NO;
-    }
-    return _displayScrollView;
-}
-
-- (NSMutableArray *)pageArray {
-    if (!_pageArray) {
-        _pageArray = [NSMutableArray array];
-    }
-    return _pageArray;
-}
-
-
-- (KSWebSocketManager *)socketManager {
-    if (!_socketManager) {
-        _socketManager = [[KSWebSocketManager alloc] init];
-    }
-    return _socketManager;
-}
-
-- (KSSliderView *)sliderView {
-    if (!_sliderView) {
-        _sliderView = [[KSSliderView alloc] initWithFrame:CGRectMake(0, 0, 50, 250)];
-        _sliderView.backgroundColor = [UIColor clearColor];
-        _sliderView.rateValue = self.currentSpeed;
-        _sliderView.isVertical = YES;
-        _sliderView.delegate = self;
-    }
-    return _sliderView;
-}
-
-- (NoWiredTipsAlert *)wiredAlert {
-    if (!_wiredAlert) {
-        _wiredAlert = [NoWiredTipsAlert shareInstance];
-        _wiredAlert.frame = CGRectMake(0, 0, KLandscapeWidth, KLandscapeHeight);
-    }
-    return _wiredAlert;
-}
-- (UIView *)viewContainer {
-    if (!_viewContainer) {
-        _viewContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KLandscapeWidth, KLandscapeHeight)];
-    }
-    return _viewContainer;
-}
-
-- (KSVideoRecordManager *)videoRecordManager {
-    if (!_videoRecordManager) {
-        MJWeakSelf;
-        _videoRecordManager = [[KSVideoRecordManager alloc] initSessionRecordCallback:^(BOOL isSuccess, NSString * _Nullable message) {
-            if (isSuccess) {
-                [weakSelf showSuccessMessage:message];
-            }
-            else {
-                if (![NSString isEmptyString:message]) {
-                    [LOADING_MANAGER MBShowAUTOHidingInWindow:message];
-                }
-            }
-        }];
-    }
-    return _videoRecordManager;
-}
-
-- (UIButton *)evaluateButton {
-    if (!_evaluateButton) {
-        _evaluateButton = [UIButton buttonWithType:UIButtonTypeCustom];
-        _evaluateButton.layer.cornerRadius = 22.0f;
-        [_evaluateButton setBackgroundColor:THEMECOLOR];
-        _evaluateButton.frame = CGRectMake((KLandscapeWidth - 150)/2.0f, KLandscapeHeight - 44 - 20, 150, 44);
-        [_evaluateButton.titleLabel setFont:[UIFont systemFontOfSize:18.0f weight:UIFontWeightMedium]];
-        [_evaluateButton setTitle:@"开始演奏" forState:UIControlStateNormal];
-        [_evaluateButton setTitle:@"√结束演奏" forState:UIControlStateSelected];
-        [_evaluateButton addTarget:self action:@selector(evaluateButtonAction:) forControlEvents:UIControlEventTouchUpInside];
-    }
-    return _evaluateButton;
-}
-
-- (void)evaluateButtonAction:(UIButton *)sender {
-    sender.selected = !sender.selected;
-    if (sender.isSelected) {
-        [self startEvaluateing];
-    }
-    else {
-        [self endEvaluating];
-    }
-}
-
-- (void)showSuccessMessage:(NSString *)message {
-    [LOADING_MANAGER MBShowAUTOHidingInWindow:message];
-}
-
-#pragma mark ----- KSSliderView delegate
-- (void)rateChangeAction:(NSInteger)rate {
-    self.currentSpeed = rate;
-    CloudControlButton *playButton = [self.headView viewWithTag:BUTTON_TAG_SPEED];
-    [playButton showSpeed:rate];
-    
-    // 速度写入本地文件中
-    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-        
-        NSString *filePath = [CloudSongMessageModel getSaveSpeedPath];
-        NSDictionary *speedDic = [NSMutableDictionary dictionaryWithContentsOfFile:filePath];
-        NSMutableDictionary *saveDic = [NSMutableDictionary dictionaryWithDictionary:speedDic];
-        [saveDic setValue:@(rate) forKey:self.songMessageSource.examSongId];
-        NSError *err = nil;
-        if (@available(iOS 11.0, *)) {
-            [saveDic writeToURL:[NSURL fileURLWithPath:filePath] error:&err];
-        } else {
-            // Fallback on earlier versions
-            [saveDic writeToURL:[NSURL fileURLWithPath:filePath] atomically:YES];
-        }
-    });
-    
-    
-    double playRate = rate / self.playerEngine.baseRate;
-    [self.playerEngine setMusicPlayerSpeed:playRate];
-}
-
-#pragma mark ------ cloud function
-// 点击开始评测按钮
-- (void)startEvaluateing {
-    [self configRecordManager];
-    self.hasSendStartMessage = NO;
-    PREMISSIONTYPE isOk = [RecordCheckManager checkMicPermissionAvaiable];
-    if (isOk == PREMISSIONTYPE_YES) {
-        [self configXMLInfo];
-        // 如果socket 连上了
-        if (self.socketManager.socketReadyState == SR_OPEN) {
-            NSDictionary *content = self.evaluatParm;
-            NSString *sendData = [self configDataCommond:@"musicXml" body:content type:@"SOUND_COMPARE"];
-            [self sendDataToSocketService:sendData];
-            NSLog(@"------ send music xml info");
-            self.hasSendStartMessage = YES;
-            // 开始评测
-            [self showBeatBeforeEvaluating];
-        }
-        else {
-            [self connectSocketService];
-        }
-    }
-    else {
-        // 停止评测功能
-        [self cancelEvaluating];
-        [self showErrorMessage:@"没有麦克风权限"];
-    }
-}
-
-- (void)setIsEvaluating:(BOOL)isEvaluating {
-    _isEvaluating = isEvaluating;
-    if (isEvaluating) {
-        if (self.isPlaying) {
-            [self stopPlayAction];
-            
-        }
-        if (self.needShowFinger == YES) {
-            self.needShowFinger = NO;
-            [self displayFingerView];
-        }
-        [self.view addSubview:self.evaluateButton];
-        [self ForbiddenButton:YES];
-    }
-    else {
-        // 重置页面数据
-        if (_isPlaying) { // 如果在评测状态下
-            [self stopPlayAction];
-            [self endEvaluating];
-        }
-        [self displayCourseToFirstNode];
-        [self.playerEngine setProgressTime:0.0f];
-        [self.evaluateButton removeFromSuperview];
-        [self ForbiddenButton:NO];
-        if (self.showFinger == YES && self.fingerImageDic != nil) {
-            self.needShowFinger = YES;
-            [self displayFingerView];
-        }
-    }
-}
-
-- (void)ForbiddenButton:(BOOL)isForbidden {
-    for (NSInteger indexTag = 1001; indexTag < 1007; indexTag++) {
-        CloudControlButton *button = [self.headView viewWithTag:indexTag];
-        button.userInteractionEnabled = !isForbidden;
-        button.alpha =  isForbidden ? 0.6f : 1.0f;
-    }
-}
-
-
-#pragma mark ----- 节拍
-- (void)showBeatBeforePlay {
-    KSCloudBeatView *beatView = [KSCloudBeatView shareInstanceWithBeatType:self.beatType speed:self.currentSpeed repeatCount:1 supplement:0];
-    MJWeakSelf;
-    [beatView startPlayWithEndCallback:^(BOOL isCancle) {
-        if (isCancle) { // 取消
-            [weakSelf resetPlayButtonStatus];
-        }
-        else { // 开始播放
-            [weakSelf playAction];
-        }
-    }];
-    [self.view addSubview:beatView];
-}
-
-- (void)showBeatBeforeEvaluating {
-    KSCloudBeatView *beatView = [KSCloudBeatView shareInstanceWithBeatType:self.beatType speed:self.currentSpeed repeatCount:1 supplement:0];
-    MJWeakSelf;
-    [beatView startPlayWithEndCallback:^(BOOL isCancle) {
-        if (isCancle) { // 取消
-            [weakSelf cancelEvaluating];
-        }
-        else { // 开始播放
-            [weakSelf startPlayAndRecord];
-        }
-    }];
-    [self.view addSubview:beatView];
-}
-
-#pragma mark ---- 评测功能
-
-- (void)startPlayAndRecord {
-    if (self.cameraOn && self.saveVideo) {
-        [self startCapture];
-    }
-    if (self.isChooseMeasure) { // 重置选段
-        [self resetChooseMeasureStatus];
-    }
-    [self clearAllColorDisplayView];
-    CGFloat rate = self.currentSpeed / self.playerEngine.baseRate;
-    [self.playerEngine setMusicPlayerSpeed:rate];
-    [self.playerEngine setProgressTime:0.0f];
-    [self displayCourseToFirstNode];
-    [self playAction];
-    [self startRecording];
-    
-    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
-        // 发送时间校准消息
-        NSDictionary *bodyParm = @{
-            @"offsetTime" :@(0.000),
-        };
-        NSString *realStartTime = @"audioPlayStart";
-        NSString *realStart = [self configDataCommond:realStartTime body:bodyParm type:@"SOUND_COMPARE"];
-        [self sendDataToSocketService:realStart];
-        NSLog(@"--------- send check time message");
-    });
-}
-
-- (void)resetChooseMeasureStatus {
-    self.isChooseMeasure = NO;
-    // 清理全部
-    self.startMeasure = -1;
-    self.endMeasure = -1;
-    self.lastPlayNodeIndex = 0;
-    self.playerEngine.startTime = 0.0f;
-    self.playerEngine.endTime = 0.0f;
-    CloudControlButton *button = [self.headView viewWithTag:BUTTON_TAG_SELECT];
-    button.isSelected = NO;
-}
-
-- (void)configXMLInfo {
-    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
-    [dic setValue:@(0) forKey:@"beatLength"];
-    [dic setValue:@"IOS" forKey:@"platform"];
-    
-    [dic setValue:self.songMessageSource.behaviorId forKey:@"behaviorId"];
-    [dic setValue:@"1638175609911244308" forKey:@"uuid"];
-    [dic setValue:self.songMessageSource.detailId forKey:@"detailId"];
-    [dic setValue:self.songMessageSource.examSongId forKey:@"examSongId"];
-    [dic setValue:self.songMessageSource.subjectId forKey:@"subjectId"];
-    [dic setValue:self.songMessageSource.examSongId forKey:@"id"];
-    [dic setValue:self.songMessageSource.xmlUrl forKey:@"xmlUrl"];
-    // head level
-    [dic setValue:self.level forKey:@"heardLevel"];
-    
-    // 设置速度
-    [dic setValue:@(self.currentSpeed) forKey:@"speed"];
-    NSMutableArray *newNodeArray = [self configNodeArrayWithSpeed:self.currentSpeed];
-    [dic setValue:newNodeArray forKey:@"musicXmlInfos"];
-    
-    self.evaluatParm = dic;
-}
-
-- (NSMutableArray *)configNodeArrayWithSpeed:(NSInteger)speed {
-    NSMutableArray *sourceArray = [NSMutableArray array];
-    if (speed == 120) {
-        sourceArray = [NSMutableArray arrayWithArray:self.nodeArray];
-        return sourceArray;
-    }
-    for (NSMutableDictionary *parm in self.nodeArray) {
-        NSMutableDictionary *node = [parm mutableCopy];
-        float timeSapmle = [node ks_floatValueForKey:@"timeStamp"];
-        float duration = [node ks_floatValueForKey:@"duration"];
-        timeSapmle = timeSapmle * (120.0 / speed);
-        duration = duration * (120.0 / speed);
-        [node setValue:@(timeSapmle) forKey:@"timeStamp"];
-        [node setValue:@(duration) forKey:@"duration"];
-        [sourceArray addObject:node];
-    }
-    return sourceArray;
-}
-
-/* 停止评测功能 */
-- (void)endEvaluating {
-    [self stopPlayAction];
-    self.evaluateButton.selected = NO;
-    self.evaluatParm = nil;
-    [self stopRecordService];
-    [self sendEndMessage];
-    [self stopCapatureVideo];
-}
-
-/* 取消评测*/
-- (void)cancelEvaluating {
-    [self stopPlayAction];
-    self.evaluateButton.selected = NO;
-    self.evaluatParm = nil;
-    [self stopRecordService];
-    [self sendEndMessage];
-    [self stopCapatureVideo];
-}
-
-// 如果开启了保存相册和摄像头 结束评测时停止录制
-- (void)stopCapatureVideo {
-    if (self.cameraOn && self.saveVideo) {
-        [self endCapture];
-    }
-}
-
-// 是否带耳机检测
-- (void)checkIsWiredHeadsetOnCallback:(void(^)(void))callback {
-    AUDIODEVICE_TYPE type = [KSAQRecordManager queryAudioOutputDeviceType];
-    NSString *valueStr = @"";
-    BOOL checkIsWired = NO;
-    switch (type) {
-        case AUDIODEVICE_TYPE_HEADPHONE:
-        {
-            valueStr = @"有线耳机";
-            checkIsWired = YES;
-        }
-            break;
-        case AUDIODEVICE_TYPE_BLUETOOTH:
-        {
-            valueStr = @"蓝牙耳机";
-            checkIsWired = YES;
-        }
-            break;
-        case AUDIODEVICE_TYPE_NONE:
-        {
-            valueStr = @"";
-            checkIsWired = NO;
-        }
-            break;
-        default:
-            break;
-    }
-    
-    if (checkIsWired == NO) { // 未带耳机弹窗提示
-        [self showNoWiredTipsAlertCallback:^{
-            callback();
-        }];
-    }
-    
-}
-
-- (void)showNoWiredTipsAlertCallback:(void(^)(void))callback {
-    if (![self.view.subviews containsObject:self.wiredAlert]) {
-        [self.wiredAlert showAlertInView:self.view callback:^{
-            callback();
-        }];
-    }
-}
-
-/* 开始录音*/
-- (void)startRecording {
-    self.isCompareStart = YES;
-    [self startRecordService];
-}
-
-/* 停止录音*/
-- (void)endRecording {
-    [self stopRecordService];
-}
-
-/* 开始录制*/
-- (void)startCapture {
-    // 评测的时候 生成video时会合成声轨
-    BOOL isIgnoreAudio = self.isEvaluating;
-    [self.videoRecordManager setIgnoreAudio:isIgnoreAudio];
-    [RecordCheckManager checkPhotoLibraryPremissionAvaiable];
-    self.videoRecordManager.audioUrl = self.AQManager.audioUrl;
-    [self.videoRecordManager startRecord];
-}
-
-/* 结束录制*/
-- (void)endCapture {
-    if (self->_videoRecordManager) {
-        [self.videoRecordManager stopRecord];
-    }
-}
-/* 开始校音*/
-- (void)startSoundCheck {
-    [self showSoundCheckView];
-    
-    [self configRecordManager];
-    self.isCompareStart = NO;
-    self.isSoundCheckStart = YES;
-    [self startRecordService];
-}
-
-- (void)showSoundCheckView {
-    self.checkView = [SoundCheckView shareInstance];
-    MJWeakSelf;
-    [self.checkView configSoundCheckWithSubjectId:self.songMessageSource.subjectId callback:^(CLOSEACTION action) {
-        if (action == CLOSEACTION_SUCCESS) {
-            [weakSelf showSuccessMessage:@"校音成功"];
-        }
-        else if (action == CLOSEACTION_CLOSECHECK) { // 关闭校音
-            weakSelf.soundCheckOn = NO;
-            NSDictionary *config = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"cloudConfig"];
-            NSMutableDictionary *configDict = [NSMutableDictionary dictionaryWithDictionary:config];
-            [configDict setValue:@(NO) forKey:@"soundCheck"];
-            [[NSUserDefaults standardUserDefaults] setObject:configDict forKey:@"cloudConfig"];
-            [[NSUserDefaults standardUserDefaults] synchronize];
-        }
-        [weakSelf endSoundCheck];
-    }];
-    self.checkPitch = self.checkView.pitch;
-    self.checkView.frame = CGRectMake(0, 0, KLandscapeWidth, KLandscapeHeight);
-    [self.view addSubview:self.checkView];
-}
-
-/* 结束校音*/
-- (void)endSoundCheck {
-    // 结束校音
-    self.isSoundCheckStart = NO;
-    [self stopRecordService];
-}
-
-/* 上传视频*/
-- (void)videoUpdate {
-    
-    if (self.videoRecordManager) {
-//        MJWeakSelf;
-//        [self.videoRecordManager uploadRecordVideoSuccess:^(NSString * _Nonnull videoUrl) {
-//            if (videoUrl) {
-//                [weakSelf sendUploadMessage:videoUrl];
-//            }
-//        } failure:^(NSString * _Nonnull desc) {
-//            [LOADING_MANAGER MBShowAUTOHidingInWindow:@"视频上传失败"];
-//        }];
-    }
-}
-
-- (void)sendUploadMessage:(NSString *)videoUrl {
-    NSDictionary *header = @{@"commond" : @"videoUpdate",
-                             @"type" : @"SOUND_COMPARE",
-                             @"status" : @(200),
-    };
-    NSMutableDictionary *body = [NSMutableDictionary dictionary];
-    [body setValue:@(self.recordId) forKey:@"recordId"];
-    if ([NSString isEmptyString:videoUrl]) {
-        [body setValue:@(self.recordId) forKey:@"recordId"];
-    }
-        
-    NSMutableDictionary *content = [NSMutableDictionary dictionary];
-    [content setValue:header forKey:@"header"];
-    [content setValue:body forKey:@"body"];
-    [content setValue:@"1638175609911244308" forKey:@"uuid"];
-    
-    NSString *sendData = [content mj_JSONString];
-    [self sendDataToSocketService:sendData];
-    [LOADING_MANAGER MBShowAUTOHidingInWindow:@"上传成功"];
-}
-
-- (void)dealloc {
-    [[NSNotificationCenter defaultCenter] removeObserver:self];
-    NSLog(@"------- cloud dealloc");
-}
-
-- (TrackChooseView *)trackChooseView {
-    if (!_trackChooseView) {
-        _trackChooseView = [TrackChooseView shareInstanceWithFullTrackArray:self.playerEngine.instrumentTrackNameArray];
-        MJWeakSelf;
-        [_trackChooseView chooseTrackCallback:^(NSMutableArray * _Nullable trackNameArray) {
-            [weakSelf operationWithTrackNameArray:trackNameArray];
-        }];
-    }
-    return _trackChooseView;
-}
-
-- (void)operationWithTrackNameArray:(NSMutableArray *)trackNameArray {
-    [self.playerEngine muteTrackWithTrackNameExclude:trackNameArray];
-}
-
-/*
-#pragma mark - Navigation
-
-// In a storyboard-based application, you will often want to do a little preparation before navigation
-- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
-    // Get the new view controller using [segue destinationViewController].
-    // Pass the selected object to the new view controller.
-}
-*/
-
-@end

+ 0 - 33
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/CloudSongMessageModel.h

@@ -1,33 +0,0 @@
-//
-//  CloudSongMessageModel.h
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/9.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface CloudSongMessageModel : NSObject
-
-@property (nonatomic, strong) NSString *detailId;  // 返回的id
-
-@property (nonatomic, strong) NSString *subjectId;     // 声部id
-
-@property (nonatomic, strong) NSString *examSongId;    // 曲目id
-
-@property (nonatomic, strong) NSString *examSongName;  // 曲目名称
-
-@property (nonatomic, strong) NSString *zipUrl;
-
-@property (nonatomic, strong) NSString *xmlUrl;
-
-@property (nonatomic, strong) NSString *behaviorId; // 统计批次ID
-
-+ (NSString *)getSaveSpeedPath;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 35
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/CloudSongMessageModel.m

@@ -1,35 +0,0 @@
-//
-//  CloudSongMessageModel.m
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/9.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import "CloudSongMessageModel.h"
-
-@implementation CloudSongMessageModel
-
-+ (NSString *)getSaveSpeedPath {
-    //  在Documents目录下创建一个名为AudioSpeedFile的文件夹
-    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject] stringByAppendingPathComponent:@"AudioSpeedFile"];
-    NSLog(@"%@",path);
-    
-    NSFileManager *fileManager = [NSFileManager defaultManager];
-    BOOL isDir = FALSE;
-    BOOL isDirExist = [fileManager fileExistsAtPath:path isDirectory:&isDir];
-    if(!(isDirExist && isDir)) {
-        BOOL bCreateDir = [fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
-        if(!bCreateDir){
-            NSLog(@"创建文件夹失败!");
-        }
-        NSLog(@"创建文件夹成功,文件路径%@",path);
-    }
-    
-    path = [path stringByAppendingPathComponent:@"songSpeed.plist"];
-    NSLog(@"file path:%@",path);
-    return path;
-}
-
-
-@end

+ 0 - 1206
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/FingerList.plist

@@ -1,1206 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>flute</key>
-	<dict>
-		<key>60</key>
-		<array>
-			<string>flute13,flute12,flute11,flute1,flute10,flute8,flute3,flute6</string>
-		</array>
-		<key>61</key>
-		<array>
-			<string>flute13,flute12,flute11,flute1,flute10,flute8,flute3,flute7</string>
-		</array>
-		<key>62</key>
-		<array>
-			<string>flute13,flute12,flute11,flute1,flute10,flute8,flute3</string>
-		</array>
-		<key>63</key>
-		<array>
-			<string>flute13,flute12,flute11,flute1,flute10,flute8,flute3,flute5</string>
-		</array>
-		<key>64</key>
-		<array>
-			<string>flute13,flute12,flute11,flute1,flute10,flute8,flute5</string>
-		</array>
-		<key>65</key>
-		<array>
-			<string>flute13,flute12,flute11,flute1,flute10,flute5</string>
-		</array>
-		<key>66</key>
-		<array>
-			<string>flute13,flute12,flute11,flute1,flute3,flute5</string>
-		</array>
-		<key>67</key>
-		<array>
-			<string>flute13,flute12,flute11,flute1,flute5</string>
-		</array>
-		<key>68</key>
-		<array>
-			<string>flute13,flute12,flute11,flute1,flute4,flute5</string>
-		</array>
-		<key>69</key>
-		<array>
-			<string>flute13,flute12,flute1,flute5</string>
-		</array>
-		<key>70</key>
-		<array>
-			<string>flute13,flute0,flute5</string>
-			<string>flute13,flute10,flute1,flute5</string>
-		</array>
-		<key>71</key>
-		<array>
-			<string>flute13,flute1,flute5</string>
-		</array>
-		<key>72</key>
-		<array>
-			<string>flute13,flute5</string>
-		</array>
-		<key>73</key>
-		<array>
-			<string>flute5</string>
-		</array>
-		<key>74</key>
-		<array>
-			<string>flute12,flute11,flute10,flute8,flute3,flute1</string>
-		</array>
-		<key>75</key>
-		<array>
-			<string>flute12,flute11,flute10,flute8,flute3,flute5,flute1</string>
-		</array>
-		<key>76</key>
-		<array>
-			<string>flute13,flute12,flute11,flute1,flute10,flute8,flute5</string>
-		</array>
-		<key>77</key>
-		<array>
-			<string>flute13,flute12,flute11,flute1,flute10,flute5</string>
-		</array>
-		<key>78</key>
-		<array>
-			<string>flute13,flute12,flute11,flute1,flute3,flute5</string>
-		</array>
-		<key>79</key>
-		<array>
-			<string>flute13,flute12,flute11,flute1,flute5</string>
-		</array>
-		<key>80</key>
-		<array>
-			<string>flute13,flute12,flute11,flute1,flute4,flute5</string>
-		</array>
-		<key>81</key>
-		<array>
-			<string>flute13,flute12,flute1,flute5</string>
-		</array>
-		<key>82</key>
-		<array>
-			<string>flute13,flute0,flute5</string>
-			<string>flute13,flute10,flute1,flute5</string>
-		</array>
-		<key>83</key>
-		<array>
-			<string>flute13,flute1,flute5</string>
-		</array>
-		<key>84</key>
-		<array>
-			<string>flute13,flute5</string>
-		</array>
-		<key>85</key>
-		<array>
-			<string>flute5</string>
-		</array>
-		<key>86</key>
-		<array>
-			<string>flute12,flute11,flute1,flute5</string>
-		</array>
-		<key>87</key>
-		<array>
-			<string>flute13,flute12,flute11,flute1,flute10,flute8,flute3,flute5</string>
-		</array>
-		<key>88</key>
-		<array>
-			<string>flute13,flute12,flute1,flute10,flute8,flute5</string>
-		</array>
-		<key>89</key>
-		<array>
-			<string>flute13,flute11,flute1,flute5</string>
-		</array>
-	</dict>
-	<key>clarinet</key>
-	<dict>
-		<key>52</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet13,clarinet17,clarinet19</string>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet13,clarinet19</string>
-		</array>
-		<key>53</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet11,clarinet19</string>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet17,clarinet19</string>
-		</array>
-		<key>54</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet12,clarinet17,clarinet19</string>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet12,clarinet19</string>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet14</string>
-		</array>
-		<key>55</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet19</string>
-		</array>
-		<key>56</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet15,clarinet19</string>
-		</array>
-		<key>57</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet19</string>
-		</array>
-		<key>58</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet19</string>
-		</array>
-		<key>59</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet8,clarinet19</string>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet9,clarinet19</string>
-		</array>
-		<key>60</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet9</string>
-		</array>
-		<key>61</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet6,clarinet19</string>
-		</array>
-		<key>62</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet19</string>
-		</array>
-		<key>63</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet19,clarinet23</string>
-			<string>clarinet2,clarinet3,clarinet4,clarinet19</string>
-			<string>clarinet2,clarinet7,clarinet19</string>
-		</array>
-		<key>64</key>
-		<array>
-			<string>clarinet2,clarinet19</string>
-		</array>
-		<key>65</key>
-		<array>
-			<string>clarinet19</string>
-		</array>
-		<key>66</key>
-		<array>
-			<string>clarinet2</string>
-			<string>clarinet19,clarinet22,clarinet23</string>
-		</array>
-		<key>67</key>
-		<array>
-			<string></string>
-		</array>
-		<key>68</key>
-		<array>
-			<string>clarinet1</string>
-		</array>
-		<key>69</key>
-		<array>
-			<string>clarinet0</string>
-		</array>
-		<key>70</key>
-		<array>
-			<string>clarinet0,clarinet18</string>
-		</array>
-		<key>71</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet13,clarinet17,clarinet18,clarinet19</string>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet13,clarinet18,clarinet19</string>
-		</array>
-		<key>72</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet12,clarinet18,clarinet19</string>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet17,clarinet18,clarinet19</string>
-		</array>
-		<key>73</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet12,clarinet18,clarinet19</string>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet12,clarinet17,clarinet18,clarinet19</string>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet14,clarinet18,clarinet19</string>
-		</array>
-		<key>74</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet18,clarinet19</string>
-		</array>
-		<key>75</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet10,clarinet15,clarinet18,clarinet19</string>
-		</array>
-		<key>76</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet8,clarinet18,clarinet19</string>
-		</array>
-		<key>77</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet18,clarinet19</string>
-		</array>
-		<key>78</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet8,clarinet18,clarinet19</string>
-			<string>clarinet2,clarinet3,clarinet5,clarinet7,clarinet9,clarinet18,clarinet19</string>
-		</array>
-		<key>79</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet18,clarinet19</string>
-		</array>
-		<key>80</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet5,clarinet6,clarinet18,clarinet19</string>
-		</array>
-		<key>81</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet18,clarinet19</string>
-		</array>
-		<key>82</key>
-		<array>
-			<string>clarinet2,clarinet3,clarinet18,clarinet19,clarinet23</string>
-			<string>clarinet2,clarinet3,clarinet4,clarinet18,clarinet19</string>
-			<string>clarinet2,clarinet3,clarinet7,clarinet18,clarinet19</string>
-		</array>
-		<key>83</key>
-		<array>
-			<string>clarinet2,clarinet18,clarinet19</string>
-		</array>
-		<key>84</key>
-		<array>
-			<string>clarinet18,clarinet19</string>
-		</array>
-		<key>85</key>
-		<array>
-			<string>clarinet3,clarinet5,clarinet7,clarinet8,clarinet18,clarinet19</string>
-		</array>
-		<key>86</key>
-		<array>
-			<string>clarinet3,clarinet5,clarinet7,clarinet15,clarinet18,clarinet19</string>
-		</array>
-		<key>87</key>
-		<array>
-			<string>clarinet3,clarinet5,clarinet7,clarinet9,clarinet15,clarinet18,clarinet19</string>
-			<string>clarinet3,clarinet5,clarinet8,clarinet15,clarinet18,clarinet19</string>
-		</array>
-		<key>88</key>
-		<array>
-			<string>clarinet3,clarinet5,clarinet15,clarinet18,clarinet19</string>
-		</array>
-		<key>89</key>
-		<array>
-			<string>clarinet3,clarinet5,clarinet6,clarinet15,clarinet18,clarinet19</string>
-		</array>
-	</dict>
-	<key>trumpet</key>
-	<dict>
-		<key>0</key>
-		<array>
-			<string>trumpet0,trumpet1,trumpet2</string>
-		</array>
-		<key>54</key>
-		<array>
-			<string>trumpet3,trumpet4,trumpet5</string>
-		</array>
-		<key>55</key>
-		<array>
-			<string>trumpet3,trumpet1,trumpet5</string>
-		</array>
-		<key>56</key>
-		<array>
-			<string>trumpet0,trumpet4,trumpet5</string>
-		</array>
-		<key>57</key>
-		<array>
-			<string>trumpet3,trumpet4,trumpet2</string>
-		</array>
-		<key>58</key>
-		<array>
-			<string>trumpet3,trumpet1,trumpet2</string>
-		</array>
-		<key>59</key>
-		<array>
-			<string>trumpet0,trumpet4,trumpet2</string>
-		</array>
-		<key>60</key>
-		<array>
-			<string>trumpet0,trumpet1,trumpet2</string>
-		</array>
-		<key>61</key>
-		<array>
-			<string>trumpet3,trumpet4,trumpet5</string>
-		</array>
-		<key>62</key>
-		<array>
-			<string>trumpet3,trumpet1,trumpet5</string>
-		</array>
-		<key>63</key>
-		<array>
-			<string>trumpet0,trumpet4,trumpet5</string>
-		</array>
-		<key>64</key>
-		<array>
-			<string>trumpet3,trumpet4,trumpet2</string>
-		</array>
-		<key>65</key>
-		<array>
-			<string>trumpet3,trumpet1,trumpet2</string>
-		</array>
-		<key>66</key>
-		<array>
-			<string>trumpet0,trumpet4,trumpet2</string>
-		</array>
-		<key>67</key>
-		<array>
-			<string>trumpet0,trumpet1,trumpet2</string>
-		</array>
-		<key>68</key>
-		<array>
-			<string>trumpet0,trumpet4,trumpet5</string>
-		</array>
-		<key>69</key>
-		<array>
-			<string>trumpet3,trumpet4,trumpet2</string>
-		</array>
-		<key>70</key>
-		<array>
-			<string>trumpet3,trumpet1,trumpet2</string>
-		</array>
-		<key>71</key>
-		<array>
-			<string>trumpet0,trumpet4,trumpet2</string>
-		</array>
-		<key>72</key>
-		<array>
-			<string>trumpet0,trumpet1,trumpet2</string>
-		</array>
-		<key>73</key>
-		<array>
-			<string>trumpet3,trumpet4,trumpet2</string>
-		</array>
-		<key>74</key>
-		<array>
-			<string>trumpet3,trumpet1,trumpet2</string>
-		</array>
-		<key>75</key>
-		<array>
-			<string>trumpet0,trumpet4,trumpet2</string>
-		</array>
-		<key>76</key>
-		<array>
-			<string>trumpet0,trumpet1,trumpet2</string>
-		</array>
-		<key>77</key>
-		<array>
-			<string>trumpet3,trumpet1,trumpet2</string>
-		</array>
-		<key>78</key>
-		<array>
-			<string>trumpet0,trumpet3,trumpet2</string>
-		</array>
-		<key>79</key>
-		<array>
-			<string>trumpet0,trumpet1,trumpet2</string>
-		</array>
-		<key>80</key>
-		<array>
-			<string>trumpet0,trumpet4,trumpet5</string>
-		</array>
-		<key>81</key>
-		<array>
-			<string>trumpet3,trumpet4,trumpet2</string>
-		</array>
-		<key>82</key>
-		<array>
-			<string>trumpet3,trumpet1,trumpet2</string>
-		</array>
-		<key>83</key>
-		<array>
-			<string>trumpet0,trumpet4,trumpet2</string>
-		</array>
-		<key>84</key>
-		<array>
-			<string>trumpet0,trumpet1,trumpet2</string>
-		</array>
-	</dict>
-	<key>horn</key>
-	<dict>
-		<key>53</key>
-		<array>
-			<string>horn1</string>
-		</array>
-		<key>54</key>
-		<array>
-			<string>horn2</string>
-		</array>
-		<key>55</key>
-		<array>
-			<string></string>
-		</array>
-		<key>56</key>
-		<array>
-			<string>horn2,horn3</string>
-		</array>
-		<key>57</key>
-		<array>
-			<string>horn1,horn2</string>
-		</array>
-		<key>58</key>
-		<array>
-			<string>horn1</string>
-		</array>
-		<key>59</key>
-		<array>
-			<string>horn2</string>
-		</array>
-		<key>60</key>
-		<array>
-			<string></string>
-		</array>
-		<key>61</key>
-		<array>
-			<string>horn1,horn2</string>
-		</array>
-		<key>62</key>
-		<array>
-			<string>horn1</string>
-		</array>
-		<key>63</key>
-		<array>
-			<string></string>
-		</array>
-		<key>65</key>
-		<array>
-			<string>horn1</string>
-		</array>
-		<key>66</key>
-		<array>
-			<string>horn2</string>
-		</array>
-		<key>67</key>
-		<array>
-			<string></string>
-		</array>
-		<key>68</key>
-		<array>
-			<string>horn0,horn2,horn3</string>
-		</array>
-		<key>69</key>
-		<array>
-			<string>horn0,horn1,horn2</string>
-		</array>
-		<key>70</key>
-		<array>
-			<string>horn0,horn1</string>
-		</array>
-		<key>71</key>
-		<array>
-			<string>horn0,horn2</string>
-		</array>
-		<key>72</key>
-		<array>
-			<string>horn0</string>
-		</array>
-		<key>73</key>
-		<array>
-			<string>horn0,horn2,horn3</string>
-		</array>
-		<key>74</key>
-		<array>
-			<string>horn0,horn1,horn2</string>
-		</array>
-		<key>75</key>
-		<array>
-			<string>horn0,horn1</string>
-		</array>
-		<key>76</key>
-		<array>
-			<string>horn0,horn2</string>
-		</array>
-		<key>77</key>
-		<array>
-			<string>horn0</string>
-		</array>
-		<key>78</key>
-		<array>
-			<string>horn0,horn2</string>
-		</array>
-		<key>79</key>
-		<array>
-			<string>horn0</string>
-		</array>
-		<key>80</key>
-		<array>
-			<string>horn0,horn2,horn3</string>
-		</array>
-		<key>81</key>
-		<array>
-			<string>horn0,horn1,horn3</string>
-		</array>
-		<key>82</key>
-		<array>
-			<string>horn0,horn1</string>
-		</array>
-		<key>83</key>
-		<array>
-			<string>horn0,horn2</string>
-		</array>
-		<key>84</key>
-		<array>
-			<string>horn0</string>
-		</array>
-	</dict>
-	<key>up-bass-horn</key>
-	<dict>
-		<key>0</key>
-		<array>
-			<string>up-bass-horn0,up-bass-horn1,up-bass-horn2</string>
-		</array>
-		<key>40</key>
-		<array>
-			<string>up-bass-horn3,up-bass-horn4,up-bass-horn5</string>
-		</array>
-		<key>41</key>
-		<array>
-			<string>up-bass-horn3,up-bass-horn1,up-bass-horn5</string>
-		</array>
-		<key>42</key>
-		<array>
-			<string>up-bass-horn0,up-bass-horn4,up-bass-horn5</string>
-		</array>
-		<key>43</key>
-		<array>
-			<string>up-bass-horn3,up-bass-horn4,up-bass-horn2</string>
-		</array>
-		<key>44</key>
-		<array>
-			<string>up-bass-horn3,up-bass-horn1,up-bass-horn2</string>
-		</array>
-		<key>45</key>
-		<array>
-			<string>up-bass-horn0,up-bass-horn4,up-bass-horn2</string>
-		</array>
-		<key>46</key>
-		<array>
-			<string>up-bass-horn0,up-bass-horn1,up-bass-horn2</string>
-		</array>
-		<key>47</key>
-		<array>
-			<string>up-bass-horn3,up-bass-horn4,up-bass-horn5</string>
-		</array>
-		<key>48</key>
-		<array>
-			<string>up-bass-horn3,up-bass-horn1,up-bass-horn5</string>
-		</array>
-		<key>49</key>
-		<array>
-			<string>up-bass-horn0,up-bass-horn4,up-bass-horn5</string>
-		</array>
-		<key>50</key>
-		<array>
-			<string>up-bass-horn3,up-bass-horn4,up-bass-horn2</string>
-		</array>
-		<key>51</key>
-		<array>
-			<string>up-bass-horn3,up-bass-horn1,up-bass-horn2</string>
-		</array>
-		<key>52</key>
-		<array>
-			<string>up-bass-horn0,up-bass-horn4,up-bass-horn2</string>
-		</array>
-		<key>53</key>
-		<array>
-			<string>up-bass-horn0,up-bass-horn1,up-bass-horn2</string>
-		</array>
-		<key>54</key>
-		<array>
-			<string>up-bass-horn0,up-bass-horn4,up-bass-horn5</string>
-		</array>
-		<key>55</key>
-		<array>
-			<string>up-bass-horn3,up-bass-horn4,up-bass-horn2</string>
-		</array>
-		<key>56</key>
-		<array>
-			<string>up-bass-horn3,up-bass-horn1,up-bass-horn2</string>
-		</array>
-		<key>57</key>
-		<array>
-			<string>up-bass-horn0,up-bass-horn4,up-bass-horn2</string>
-		</array>
-		<key>58</key>
-		<array>
-			<string>up-bass-horn0,up-bass-horn1,up-bass-horn2</string>
-		</array>
-		<key>59</key>
-		<array>
-			<string>up-bass-horn3,up-bass-horn4,up-bass-horn2</string>
-		</array>
-		<key>60</key>
-		<array>
-			<string>up-bass-horn3,up-bass-horn1,up-bass-horn2</string>
-		</array>
-		<key>61</key>
-		<array>
-			<string>up-bass-horn0,up-bass-horn4,up-bass-horn2</string>
-		</array>
-		<key>62</key>
-		<array>
-			<string>up-bass-horn0,up-bass-horn1,up-bass-horn2</string>
-		</array>
-		<key>63</key>
-		<array>
-			<string>up-bass-horn3,up-bass-horn1,up-bass-horn2</string>
-		</array>
-		<key>64</key>
-		<array>
-			<string>up-bass-horn0,up-bass-horn4,up-bass-horn2</string>
-		</array>
-		<key>65</key>
-		<array>
-			<string>up-bass-horn0,up-bass-horn1,up-bass-horn2</string>
-		</array>
-		<key>66</key>
-		<array>
-			<string>up-bass-horn0,up-bass-horn4,up-bass-horn5</string>
-		</array>
-		<key>67</key>
-		<array>
-			<string>up-bass-horn3,up-bass-horn4,up-bass-horn2</string>
-		</array>
-		<key>68</key>
-		<array>
-			<string>up-bass-horn3,up-bass-horn1,up-bass-horn2</string>
-		</array>
-		<key>69</key>
-		<array>
-			<string>up-bass-horn0,up-bass-horn4,up-bass-horn2</string>
-		</array>
-		<key>70</key>
-		<array>
-			<string>up-bass-horn0,up-bass-horn1,up-bass-horn2</string>
-		</array>
-	</dict>
-	<key>trombone</key>
-	<dict>
-		<key>0</key>
-		<array>
-			<string>trombone0</string>
-		</array>
-        <key>40</key>
-        <array>
-            <string>trombone6</string>
-        </array>
-        <key>41</key>
-        <array>
-            <string>trombone5</string>
-        </array>
-        <key>42</key>
-        <array>
-            <string>trombone4</string>
-        </array>
-        <key>43</key>
-        <array>
-            <string>trombone3</string>
-        </array>
-        <key>44</key>
-        <array>
-            <string>trombone2</string>
-        </array>
-        <key>45</key>
-        <array>
-            <string>trombone1</string>
-        </array>
-        <key>46</key>
-        <array>
-            <string>trombone0</string>
-        </array>
-        <key>47</key>
-        <array>
-            <string>trombone6</string>
-        </array>
-        <key>48</key>
-        <array>
-            <string>trombone5</string>
-        </array>
-        <key>49</key>
-        <array>
-            <string>trombone4</string>
-        </array>
-        <key>50</key>
-        <array>
-            <string>trombone3</string>
-        </array>
-        <key>51</key>
-        <array>
-            <string>trombone2</string>
-        </array>
-        <key>52</key>
-        <array>
-            <string>trombone1</string>
-        </array>
-        <key>53</key>
-        <array>
-            <string>trombone0</string>
-        </array>
-        <key>54</key>
-        <array>
-            <string>trombone4</string>
-        </array>
-        <key>55</key>
-        <array>
-            <string>trombone3</string>
-        </array>
-        <key>56</key>
-        <array>
-            <string>trombone2</string>
-        </array>
-        <key>57</key>
-        <array>
-            <string>trombone1</string>
-        </array>
-        <key>58</key>
-        <array>
-            <string>trombone0</string>
-        </array>
-        <key>59</key>
-        <array>
-            <string>trombone3</string>
-        </array>
-        <key>60</key>
-        <array>
-            <string>trombone2</string>
-        </array>
-        <key>61</key>
-        <array>
-            <string>trombone1</string>
-        </array>
-        <key>62</key>
-        <array>
-            <string>trombone0</string>
-        </array>
-        <key>63</key>
-        <array>
-            <string>trombone2</string>
-        </array>
-        <key>64</key>
-        <array>
-            <string>trombone1</string>
-        </array>
-        <key>65</key>
-        <array>
-            <string>trombone0</string>
-        </array>
-        <key>66</key>
-        <array>
-            <string>trombone2</string>
-        </array>
-        <key>67</key>
-        <array>
-            <string>trombone1</string>
-        </array>
-        <key>68</key>
-        <array>
-            <string>trombone2</string>
-        </array>
-        <key>69</key>
-        <array>
-            <string>trombone1</string>
-        </array>
-        <key>70</key>
-        <array>
-            <string>trombone0</string>
-        </array>
-	</dict>
-    <key>saxophone</key>
-    <dict>
-        <key>58</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4,saxophone12,saxophone16,saxophone17,saxophone18,saxophone22</string>
-        </array>
-        <key>59</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4,saxophone10,saxophone16,saxophone17,saxophone18,saxophone22</string>
-        </array>
-        <key>60</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4,saxophone16,saxophone17,saxophone18,saxophone22</string>
-        </array>
-        <key>61</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4,saxophone16,saxophone17,saxophone18,saxophone22</string>
-        </array>
-        <key>62</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4,saxophone16,saxophone17,saxophone18</string>
-        </array>
-        <key>63</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4,saxophone16,saxophone17,saxophone18,saxophone21</string>
-        </array>
-        <key>64</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4,saxophone16,saxophone17</string>
-        </array>
-        <key>65</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4,saxophone16</string>
-        </array>
-        <key>66</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4,saxophone17</string>
-            <string>saxophone1,saxophone3,saxophone4,saxophone16,saxophone20</string>
-        </array>
-        <key>67</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4</string>
-        </array>
-        <key>68</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4,saxophone9</string>
-        </array>
-        <key>69</key>
-        <array>
-            <string>saxophone1,saxophone3</string>
-        </array>
-        <key>70</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone15</string>
-            <string>saxophone1,saxophone16</string>
-            <string>saxophone1,saxophone2</string>
-        </array>
-        <key>71</key>
-        <array>
-            <string>saxophone1</string>
-        </array>
-        <key>72</key>
-        <array>
-            <string>saxophone3</string>
-        </array>
-        <key>73</key>
-        <array>
-            <string></string>
-        </array>
-        <key>74</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4,saxophone5,saxophone16,saxophone17,saxophone18</string>
-        </array>
-        <key>75</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4,saxophone5,saxophone16,saxophone17,saxophone18,saxophone21</string>
-        </array>
-        <key>76</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4,saxophone5,saxophone16,saxophone17</string>
-        </array>
-        <key>77</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4,saxophone5,saxophone16</string>
-        </array>
-        <key>78</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4,saxophone5,saxophone17</string>
-            <string>saxophone1,saxophone3,saxophone4,saxophone5,saxophone16,saxophone20</string>
-        </array>
-        <key>79</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4,saxophone5</string>
-        </array>
-        <key>80</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone4,saxophone5,saxophone9</string>
-        </array>
-        <key>81</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone5</string>
-        </array>
-        <key>82</key>
-        <array>
-            <string>saxophone1,saxophone3,saxophone5,saxophone15</string>
-            <string>saxophone1,saxophone5,saxophone16</string>
-            <string>saxophone1,saxophone2,saxophone5</string>
-        </array>
-        <key>83</key>
-        <array>
-            <string>saxophone1,saxophone5</string>
-        </array>
-        <key>84</key>
-        <array>
-            <string>saxophone3,saxophone5</string>
-            <string>saxophone1,saxophone5,saxophone14</string>
-        </array>
-        <key>85</key>
-        <array>
-            <string>saxophone5</string>
-        </array>
-        <key>86</key>
-        <array>
-            <string>saxophone5,saxophone8</string>
-        </array>
-        <key>87</key>
-        <array>
-            <string>saxophone5,saxophone6,saxophone7</string>
-        </array>
-        <key>88</key>
-        <array>
-            <string>saxophone5,saxophone7,saxophone8,saxophone13</string>
-        </array>
-        <key>89</key>
-        <array>
-            <string>saxophone5,saxophone6,saxophone7,saxophone8,saxophone13</string>
-            <string>saxophone0,saxophone3,saxophone5</string>
-        </array>
-    </dict>
-    <key>tuba</key>
-    <dict>
-        <key>0</key>
-        <array>
-            <string>tuba0,tuba1,tuba2</string>
-        </array>
-        <key>28</key>
-        <array>
-            <string>tuba3,tuba4,tuba5</string>
-        </array>
-        <key>29</key>
-        <array>
-            <string>tuba3,tuba1,tuba5</string>
-        </array>
-        <key>30</key>
-        <array>
-            <string>tuba0,tuba4,tuba5</string>
-        </array>
-        <key>31</key>
-        <array>
-            <string>tuba3,tuba4,tuba2</string>
-        </array>
-        <key>32</key>
-        <array>
-            <string>tuba3,tuba1,tuba2</string>
-        </array>
-        <key>33</key>
-        <array>
-            <string>tuba3,tuba1,tuba5</string>
-        </array>
-        <key>34</key>
-        <array>
-            <string>tuba0,tuba1,tuba2</string>
-        </array>
-        <key>35</key>
-        <array>
-            <string>tuba3,tuba4,tuba5</string>
-        </array>
-        <key>36</key>
-        <array>
-            <string>tuba3,tuba1,tuba5</string>
-        </array>
-        <key>37</key>
-        <array>
-            <string>tuba0,tuba4,tuba5</string>
-        </array>
-        <key>38</key>
-        <array>
-            <string>tuba3,tuba4,tuba2</string>
-        </array>
-        <key>39</key>
-        <array>
-            <string>tuba3,tuba1,tuba2</string>
-        </array>
-        <key>40</key>
-        <array>
-            <string>tuba0,tuba4,tuba2</string>
-        </array>
-        <key>41</key>
-        <array>
-            <string>tuba0,tuba1,tuba2</string>
-        </array>
-        <key>42</key>
-        <array>
-            <string>tuba0,tuba4,tuba5</string>
-        </array>
-        <key>43</key>
-        <array>
-            <string>tuba3,tuba4,tuba2</string>
-        </array>
-        <key>44</key>
-        <array>
-            <string>tuba3,tuba1,tuba2</string>
-        </array>
-        <key>45</key>
-        <array>
-            <string>tuba0,tuba4,tuba2</string>
-        </array>
-        <key>46</key>
-        <array>
-            <string>tuba0,tuba1,tuba2</string>
-        </array>
-        <key>47</key>
-        <array>
-            <string>tuba3,tuba4,tuba2</string>
-        </array>
-        <key>48</key>
-        <array>
-            <string>tuba3,tuba1,tuba2</string>
-        </array>
-        <key>49</key>
-        <array>
-            <string>tuba0,tuba4,tuba2</string>
-        </array>
-        <key>50</key>
-        <array>
-            <string>tuba0,tuba1,tuba2</string>
-        </array>
-        <key>51</key>
-        <array>
-            <string>tuba3,tuba1,tuba2</string>
-        </array>
-        <key>52</key>
-        <array>
-            <string>tuba0,tuba4,tuba2</string>
-        </array>
-        <key>53</key>
-        <array>
-            <string>tuba0,tuba1,tuba2</string>
-        </array>
-        <key>54</key>
-        <array>
-            <string>tuba0,tuba4,tuba5</string>
-        </array>
-        <key>55</key>
-        <array>
-            <string>tuba3,tuba4,tuba2</string>
-        </array>
-        <key>56</key>
-        <array>
-            <string>tuba3,tuba1,tuba2</string>
-        </array>
-        <key>57</key>
-        <array>
-            <string>tuba0,tuba4,tuba2</string>
-        </array>
-        <key>58</key>
-        <array>
-            <string>tuba0,tuba1,tuba2</string>
-        </array>
-    </dict>
-    <key>piccolo</key>
-    <dict>
-        <key>72</key>
-        <array>
-            <string>piccolo8,piccolo1,piccolo9,piccolo3,piccolo4,piccolo5,piccolo6,piccolo7</string>
-        </array>
-        <key>73</key>
-        <array>
-            <string>piccolo8,piccolo1,piccolo9,piccolo3,piccolo4,piccolo5,piccolo6,piccolo11</string>
-        </array>
-        <key>74</key>
-        <array>
-            <string>piccolo8,piccolo1,piccolo9,piccolo3,piccolo4,piccolo5,piccolo10</string>
-        </array>
-        <key>75</key>
-        <array>
-            <string>piccolo8,piccolo1,piccolo9,piccolo3,piccolo4,piccolo5,piccolo6</string>
-        </array>
-        <key>76</key>
-        <array>
-            <string>piccolo8,piccolo1,piccolo9,piccolo3,piccolo4,piccolo5</string>
-        </array>
-        <key>77</key>
-        <array>
-            <string>piccolo8,piccolo1,piccolo9,piccolo3,piccolo4,piccolo6,piccolo7</string>
-        </array>
-        <key>78</key>
-        <array>
-            <string>piccolo8,piccolo1,piccolo9,piccolo3,piccolo5,piccolo6</string>
-        </array>
-        <key>79</key>
-        <array>
-            <string>piccolo8,piccolo1,piccolo9,piccolo3</string>
-        </array>
-        <key>80</key>
-        <array>
-            <string>piccolo8,piccolo1,piccolo9,piccolo4,piccolo5,piccolo10</string>
-        </array>
-        <key>81</key>
-        <array>
-            <string>piccolo8,piccolo1,piccolo9</string>
-        </array>
-        <key>82</key>
-        <array>
-            <string>piccolo8,piccolo1,piccolo3,piccolo4</string>
-            <string>piccolo8,piccolo2,piccolo3,piccolo4</string>
-        </array>
-        <key>83</key>
-        <array>
-            <string>piccolo8,piccolo1</string>
-            <string>piccolo8,piccolo9,piccolo3</string>
-        </array>
-        <key>84</key>
-        <array>
-            <string>piccolo8,piccolo9</string>
-        </array>
-        <key>85</key>
-        <array>
-            <string>piccolo1,piccolo9</string>
-            <string>piccolo8</string>
-        </array>
-        <key>86</key>
-        <array>
-            <string>piccolo9</string>
-        </array>
-        <key>87</key>
-        <array>
-            <string>piccolo9,piccolo3,piccolo4,piccolo5,piccolo10</string>
-        </array>
-        <key>88</key>
-        <array>
-            <string>piccolo0,piccolo1,piccolo9,piccolo3,piccolo4,piccolo5</string>
-        </array>
-        <key>89</key>
-        <array>
-            <string>piccolo0,piccolo1,piccolo9,piccolo3,piccolo4,piccolo10</string>
-        </array>
-        <key>90</key>
-        <array>
-            <string>piccolo0,piccolo1,piccolo9,piccolo3,piccolo5</string>
-        </array>
-        <key>91</key>
-        <array>
-            <string>piccolo0,piccolo1,piccolo9,piccolo3</string>
-        </array>
-        <key>92</key>
-        <array>
-            <string>piccolo0,piccolo1,piccolo9,piccolo4</string>
-        </array>
-        <key>93</key>
-        <array>
-            <string>piccolo0,piccolo1,piccolo9</string>
-        </array>
-        <key>94</key>
-        <array>
-            <string>piccolo0,piccolo1,piccolo9,piccolo4,piccolo5,piccolo10</string>
-        </array>
-        <key>95</key>
-        <array>
-            <string>piccolo0,piccolo1,piccolo9,piccolo4,piccolo5</string>
-        </array>
-        <key>96</key>
-        <array>
-            <string>piccolo0,piccolo1,piccolo4,piccolo5</string>
-        </array>
-        <key>97</key>
-        <array>
-            <string>piccolo0,piccolo1,piccolo2,piccolo3,piccolo4,piccolo10,piccolo11</string>
-        </array>
-        <key>98</key>
-        <array>
-            <string>piccolo0,piccolo1,piccolo3,piccolo4,piccolo10,piccolo7</string>
-        </array>        
-    </dict>
-</dict>
-</plist>

+ 0 - 30
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/KSParseMessageModel.h

@@ -1,30 +0,0 @@
-//
-//  KSParseMessageModel.h
-//  MidiPlayer
-//
-//  Created by Kyle on 2021/12/2.
-//
-
-#import <Foundation/Foundation.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface KSParseMessageModel : NSObject
-
-@property (nonatomic, assign) NSInteger elementIndex;
-
-@property (nonatomic, assign) NSInteger pageIndex;
-
-@property (nonatomic, assign) double elementTimePosition;
-
-@property (nonatomic, assign) double positionX;
-
-@property (nonatomic, assign) double positionY;
-
-@property (nonatomic, assign) double elementWidth;
-
-@property (nonatomic, assign) double elementHeight;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 13
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/KSParseMessageModel.m

@@ -1,13 +0,0 @@
-//
-//  KSParseMessageModel.m
-//  MidiPlayer
-//
-//  Created by Kyle on 2021/12/2.
-//
-
-#import "KSParseMessageModel.h"
-
-@implementation KSParseMessageModel
-
-
-@end

+ 0 - 23
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/KSXMLInfoParse.h

@@ -1,23 +0,0 @@
-//
-//  KSXMLInfoParse.h
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/8.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface KSXMLInfoParse : NSObject
-
-+ (NSMutableDictionary *)getInfoFromXMLMusicFile:(NSString *)filePath;
-
-+ (double)parsePitchToHZ:(double)pitch;
-
-+ (int)ParseHZToPitch:(double)hz;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 324
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/KSXMLInfoParse.m

@@ -1,324 +0,0 @@
-//
-//  KSXMLInfoParse.m
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/8.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import "KSXMLInfoParse.h"
-#import "TBXML.h"
-
-#define GET_SUB_INT(var, sub, parent_elem)  \
-{                               \
-if(parent_elem){    \
-TBXMLElement *divisions_elem = [TBXML childElementNamed:sub parentElement:parent_elem]; \
-if (divisions_elem!=nil) {      \
-var = [[TBXML textForElement:divisions_elem] intValue];   \
-}                             \
-}   \
-}
-
-#define GET_SUB_STR(var, sub, parent_elem)  \
-{                           \
-if(parent_elem){        \
-TBXMLElement *temp_elem = [TBXML childElementNamed:sub parentElement:parent_elem]; \
-if (temp_elem!=nil) {  \
-var = [TBXML textForElement:temp_elem];   \
-}else{var=nil;}                    \
-}   \
-}
-
-#define DEFAULT_TEMPO (120)
-#define QUARTER_TICK (480) // 一个四分音符tick时钟数
-@implementation KSXMLInfoParse
-
-+ (NSMutableDictionary *)getInfoFromXMLMusicFile:(NSString *)filePath {
-    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
-    
-    NSMutableArray *infoArray = [NSMutableArray array];
-    
-    NSFileManager *fileManager = [NSFileManager defaultManager];
-    BOOL isDirExist = [fileManager fileExistsAtPath:filePath];
-    if (isDirExist == NO) {
-        // 当前文件不存在
-        return nil;
-    }
-    NSData *xml_data = [NSData dataWithContentsOfFile:filePath];
-    TBXMLElement *element;
-    NSError *error;
-    TBXML *tbxml = [[TBXML alloc] initWithXMLData:xml_data error:&error];
-    element = [tbxml rootXMLElement];
-    if (element == NULL) {
-        NSLog(@"Fail to parse xml file. error=%@", error);
-        return nil;
-    }
-    
-    NSString *name = [TBXML elementName:element];
-    if (![name isEqualToString:@"score-partwise"]) {
-        NSLog(@"this is not a MusicXML %@",name);
-        return nil;
-    }
-//    NSMutableArray *parts = [[NSMutableArray alloc] init];
-    int max_measures = 0;
-    element = element->firstChild;
-    NSInteger partIndex = 0;
-    do {
-        name = [TBXML elementName:element];
-        if ([name isEqualToString:@"part"]) {
-            NSString *part_id = [TBXML valueOfAttributeNamed:@"id" forElement:element];
-            if ([part_id isEqualToString:@"1"]) {
-                
-            }
-            int measure_index = 0;
-            int note_index = 0;
-            TBXMLElement *measure_elem = element->firstChild;
-            NSMutableArray *partNodeArray = [NSMutableArray array];
-            float tick = 0;
-            do {
-                // 解析小节信息
-               NSMutableArray *nodeArray =  [self parseMeasure:measure_elem measureIndex:&measure_index nodeIndex:&note_index tick:&tick];
-                if (nodeArray.count) {
-                    [partNodeArray addObjectsFromArray:nodeArray];
-                }
-                measure_elem = measure_elem->nextSibling;
-                measure_index++;
-                if (measure_elem==nil) {
-                    break;
-                }
-            } while (true);
-            
-            // 获取最大小节数
-            if (max_measures < measure_index) {
-                max_measures = measure_index;
-            }
-            if (partIndex == 0) {
-                infoArray = [NSMutableArray arrayWithArray:partNodeArray];
-            }
-            partIndex++;
-        }
-        element = element->nextSibling;
-        if (element==nil) {
-            break;
-        }
-    } while (true);
-    
-    [parm setValue:infoArray forKey:@"noteInfo"];
-    NSString *beat = [NSString stringWithFormat:@"%d/%d", last_numerator, last_denominator];
-    [parm setValue:beat forKey:@"beatType"];
-    return parm;
-}
-
-+ (NSMutableArray *)parseMeasure:(TBXMLElement *)measure_elem measureIndex:(int *)measureIndex nodeIndex:(int *)nodeIndex tick:(float *)tick {
-    NSMutableArray *array = [NSMutableArray array];
-    NSString *name = [TBXML elementName:measure_elem];
-    if ([name isEqualToString:@"measure"]) {
-        //notes
-        TBXMLElement *note_elem = measure_elem->firstChild;
-        do {
-            name = [TBXML elementName:note_elem];
-            if ([name isEqualToString:@"note"]) {
-               NSMutableDictionary *parm = [self parseNote:note_elem tick:tick measureIndex:measureIndex nodeIndex:nodeIndex];
-                if (parm != nil) {
-                    *nodeIndex = *nodeIndex + 1;
-                    [array addObject:parm];
-                }
-            }
-            else if ([name isEqualToString:@"attributes"]) {
-                //divisions
-                TBXMLElement *divisions_elem = [TBXML childElementNamed:@"divisions" parentElement:note_elem];
-                if (divisions_elem != nil) {
-                    last_divisions = [[TBXML textForElement:divisions_elem] intValue];
-                }
-                
-                //time
-                TBXMLElement *time_elem = [TBXML childElementNamed:@"time" parentElement:note_elem];
-                if(time_elem != nil)
-                {
-                    //beats
-                    GET_SUB_INT(last_numerator, @"beats", time_elem);
-                    //beat-type
-                    GET_SUB_INT(last_denominator, @"beat-type", time_elem);
-                }
-            }
-            note_elem = note_elem->nextSibling;
-            
-            if (note_elem==nil) {
-                break;
-            }
-        } while (true);
-    }
-    else {
-        NSLog(@"error unknow element:%@", name);
-    }
-    return array;
-}
-
-+ (NSMutableDictionary *)parseNote:(TBXMLElement *)note_elem tick:(float *)tick measureIndex:(int *)measureIndex nodeIndex:(int *)nodeIndex {
-    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
-    NSString *name = [TBXML elementName:note_elem];
-    if (note_elem==nil) {
-        return nil;
-    }
-    if ([name isEqualToString:@"note"]) {
-        BOOL isChord = NO, isRest = NO;
-        BOOL isListen = NO;
-        int duration=0;
-        int pitch_step = 0,pitch_octave = 0,pitch_alter = 0,note_value = 0;
-        NSInteger noteDenominator = 1;
-        TBXMLElement *elem = note_elem->firstChild;
-        while (elem) {
-            name = [TBXML elementName:elem];
-            if ([name isEqualToString:@"duration"]) { // 时值
-                int nodeDuration = [[TBXML textForElement:elem] intValue];
-                duration = nodeDuration * 1.0 / last_divisions * QUARTER_TICK;
-            }
-            else if ([name isEqualToString:@"type"]) { // 音符类型
-                NSString* type = nil;           //256th, 128th, 64th, 32nd, 16th, eighth, quarter, half, whole, breve, and long
-                GET_SUB_STR(type, @"type", note_elem);
-                noteDenominator = [self noteType:type];
-            }
-            else if ([name isEqualToString:@"chord"]) {
-                isChord = YES;
-            }
-            else if ([name isEqualToString:@"rest"]) { // 休息
-                isRest = YES;
-            }
-            else if ([name isEqualToString:@"pitch"]) { // 音阶
-                NSString *step=nil;
-                GET_SUB_STR(step, @"step", elem);
-                if (step) {
-                    if ([step isEqualToString:@"C"])pitch_step=1;
-                    else if ([step isEqualToString:@"D"])pitch_step=2;
-                    else if ([step isEqualToString:@"E"])pitch_step=3;
-                    else if ([step isEqualToString:@"F"])pitch_step=4;
-                    else if ([step isEqualToString:@"G"])pitch_step=5;
-                    else if ([step isEqualToString:@"A"])pitch_step=6;
-                    else if ([step isEqualToString:@"B"])pitch_step=7;
-                    else NSLog(@"Error: unknow pitch step=%@",step);
-                }
-                GET_SUB_INT(pitch_alter, @"alter", elem);
-                GET_SUB_INT(pitch_octave, @"octave", elem);
-                note_value = [self noteValueForStep:pitch_step octave:pitch_octave alter:pitch_alter];
-            }
-            else if ([name isEqualToString:@"unpitched"]) { // 休息
-//                isRest = YES;
-                NSString *step=nil;
-                GET_SUB_STR(step, @"step", elem);
-                if (step) {
-                    if ([step isEqualToString:@"C"])pitch_step=1;
-                    else if ([step isEqualToString:@"D"])pitch_step=2;
-                    else if ([step isEqualToString:@"E"])pitch_step=3;
-                    else if ([step isEqualToString:@"F"])pitch_step=4;
-                    else if ([step isEqualToString:@"G"])pitch_step=5;
-                    else if ([step isEqualToString:@"A"])pitch_step=6;
-                    else if ([step isEqualToString:@"B"])pitch_step=7;
-                    else NSLog(@"Error: unknow pitch step=%@",step);
-                }
-                GET_SUB_INT(pitch_alter, @"alter", elem);
-                GET_SUB_INT(pitch_octave, @"octave", elem);
-                note_value = [self noteValueForStep:pitch_step octave:pitch_octave alter:pitch_alter];
-            }
-            else if ([name isEqualToString:@"lyric"]) { // 歌词  获取listen play
-                NSString *text = @"";
-                GET_SUB_STR(text, @"text", elem);
-                if ([text containsString:@"listen"] || [text containsString:@"Listen"]) {
-                    isListen = YES;
-                }
-            }
-            elem = elem->nextSibling;
-        }
-        // 解析
-        if (isRest) {
-            *tick = *tick + duration;
-            return nil;
-        }
-        else if (isChord) {
-            return nil;
-        }
-        else {
-            
-            // timeStamp duration frequency nextFrequency measureIndex dontEvaluating musicalNotesIndex
-            // tick 转 时间
-            // 一拍时常 beatDuration
-            double beatDuration = 60.0f / DEFAULT_TEMPO;
-            // tick 时常
-            // 获取一个四分音符时常
-            double quaterDuartion = beatDuration * last_denominator / 4;
-            double tickDuration =  quaterDuartion / QUARTER_TICK * 1000;
-            // 计算频率
-            float timeStamp = *tick * tickDuration;
-            float durationStamp = duration * tickDuration;
-            float frequency =  [self parsePitchToHZ:note_value];
-            float nextFrequency =  [self parsePitchToHZ:note_value+1];
-            
-            [parm setValue:@(timeStamp) forKey:@"timeStamp"];
-            [parm setValue:@(durationStamp) forKey:@"duration"];
-            [parm setValue:@(frequency) forKey:@"frequency"];
-            [parm setValue:@(nextFrequency) forKey:@"nextFrequency"];
-            [parm setValue:@(isListen) forKey:@"dontEvaluating"];
-            [parm setValue:@(*measureIndex) forKey:@"measureIndex"];
-            [parm setValue:@(*nodeIndex) forKey:@"musicalNotesIndex"];
-            [parm setValue:@(noteDenominator) forKey:@"denominator"];
-            [parm setValue:@(note_value) forKey:@"note_value"];
-            *tick = *tick + duration;
-        }
-    }
-    
-    return parm;
-}
-
-+ (double)parsePitchToHZ:(double)pitch {
-    return pow(2, (pitch - 69)/12)*442;
-}
-
-+ (int)ParseHZToPitch:(double)hz {
-    return log2(hz);
-}
-
-
-//pitch_step:1..7
-//pitch_alter:-1,0,+1
-+ (int)noteValueForStep:(int)pitch_step octave:(int)pitch_octave alter:(int)pitch_alter {
-    int note_value=(1+pitch_octave)*12+pitch_alter;
-    if (pitch_step==2) { //D
-        note_value+=2;
-    }else if (pitch_step==3) { //E
-        note_value+=4;
-    }else if (pitch_step==4) { //F
-        note_value+=5;
-    }else if (pitch_step==5) { //G
-        note_value+=7;
-    }else if (pitch_step==6) { //A
-        note_value+=9;
-    }else if (pitch_step==7) { //B
-        note_value+=11;
-    }
-    return note_value;
-}
-
-
-+ (NSInteger)noteType:(NSString *)type{
-    NSInteger noteDenominator = 0;
-    if ([NSString isEmptyString:type]) {
-        noteDenominator = 1;
-    }
-    else if ([type isEqualToString:@"whole"]) {
-        noteDenominator = 1;
-    }else if ([type isEqualToString:@"half"]) {
-        noteDenominator = 2;
-    }else if ([type isEqualToString:@"quarter"]) {
-        noteDenominator = 4;
-    }else if ([type isEqualToString:@"eighth"]) {
-        noteDenominator = 8;
-    }else if ([type isEqualToString:@"16th"]) {
-        noteDenominator = 16;
-    }else {
-        noteDenominator = 32;
-    }
-    return noteDenominator;
-}
-
-static int last_divisions = 0; // 四分音符标准时常
-static int last_numerator = 4, last_denominator = 4;
-@end

+ 0 - 24
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/KYSourceParseManager.h

@@ -1,24 +0,0 @@
-//
-//  KYSourceParseManager.h
-//  MidiPlayer
-//
-//  Created by Kyle on 2021/12/2.
-//
-
-#import <Foundation/Foundation.h>
-#import "KSParseMessageModel.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface KYSourceParseManager : NSObject
-
-@property (nonatomic, strong) NSMutableArray *measureMessageArray;
-
-@property (nonatomic, strong) NSMutableArray *nodeMessageArray;
-
-
-- (BOOL)parseMessageSource:(NSString *)measureSourcePath nodeSource:(NSString *)nodeSourcePath;
- 
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 145
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/KYSourceParseManager.m

@@ -1,145 +0,0 @@
-//
-//  KYSourceParseManager.m
-//  MidiPlayer
-//
-//  Created by Kyle on 2021/12/2.
-//
-
-#import "KYSourceParseManager.h"
-#import "TBXML.h"
-
-
-@implementation KYSourceParseManager
-
-- (BOOL)parseMessageSource:(NSString *)measureSourcePath nodeSource:(NSString *)nodeSourcePath {
-    NSFileManager *fileManager = [NSFileManager defaultManager];
-    BOOL measureFileExist = [fileManager fileExistsAtPath:measureSourcePath];
-    BOOL nodeFileExist = [fileManager fileExistsAtPath:nodeSourcePath];
-    if (measureFileExist == NO || nodeFileExist == NO) {
-        NSLog(@"文件不存在");
-        return NO;
-    }
-    TBXMLElement *element;
-    NSError *error;
-    NSData *measureData = [NSData dataWithContentsOfFile:measureSourcePath];
-    TBXML *tbxml = [[TBXML alloc] initWithXMLData:measureData error:&error];
-    if (error) {
-        NSLog(@"%@", error.description);
-        return NO;
-    }
-    element = [tbxml rootXMLElement];
-    if (element == nil) {
-        NSLog(@"Fail to parse xml file. error=%@", error);
-        return NO;
-    }
-    NSString *name = [TBXML elementName:element];
-    
-    if ([name isEqualToString:@"score"]) {
-        self.measureMessageArray = [self parseScoreWithSource:element];
-    }
-    
-    NSData *nodeData = [NSData dataWithContentsOfFile:nodeSourcePath];
-    TBXML *nodeTbxml = [[TBXML alloc] initWithXMLData:nodeData error:&error];
-    if (error) {
-        NSLog(@"%@", error.description);
-        return NO;
-    }
-    TBXMLElement *nodeElement = [nodeTbxml rootXMLElement];
-    if (nodeElement == nil) {
-        NSLog(@"Fail to parse xml file. error=%@", error);
-        return NO;
-    }
-    NSString *nodeName = [TBXML elementName:nodeElement];
-    if ([nodeName isEqualToString:@"score"]) {
-        self.nodeMessageArray = [self parseScoreWithSource:nodeElement];
-    }
-    return YES;
-}
-
-- (NSMutableArray *)parseScoreWithSource:(TBXMLElement *)element {
-    NSMutableArray *sourceArray = [NSMutableArray array];
-    NSMutableArray *positionArray = [NSMutableArray array];
-    NSMutableArray *timeArray = [NSMutableArray array];
-    TBXMLElement *temp_elem = element->firstChild;
-    do {
-        NSString *name = [TBXML elementName:temp_elem];
-        if ([name isEqualToString:@"elements"]) { // 位置信息
-            positionArray = [self getDetailSourceWithElement:temp_elem];
-        }
-        else if ([name isEqualToString:@"events"]) { // 时间信息
-            timeArray = [self getDetailSourceWithElement:temp_elem];
-        }
-        
-        temp_elem = temp_elem->nextSibling;
-        if (temp_elem == nil) {
-            break;
-        }
-    } while (YES);
-    
-    // 赋值
-    if (positionArray.count != timeArray.count) {
-        return nil;
-    }
-    for (NSInteger i = 0; i < positionArray.count; i++) {
-        KSParseMessageModel *model = [[KSParseMessageModel alloc] init];
-        NSDictionary *positionDic = [positionArray objectAtIndex:i];
-        model.elementIndex = [[positionDic valueForKey:@"id"] integerValue];
-        model.positionX = [[positionDic valueForKey:@"x"] doubleValue];
-        model.positionY = [[positionDic valueForKey:@"y"] doubleValue];
-        double width = [[positionDic valueForKey:@"sx"] doubleValue];
-        if (width == 0) {
-            width = 700.0f;
-        }
-        model.elementWidth = width;
-        model.elementHeight = [[positionDic valueForKey:@"sy"] doubleValue];
-        model.pageIndex = [[positionDic valueForKey:@"page"] integerValue];
-        NSDictionary *timeDic = [timeArray objectAtIndex:i];
-        model.elementTimePosition = [[timeDic valueForKey:@"position"] integerValue];
-        [sourceArray addObject:model];
-    }
-    return sourceArray;
-}
-
-- (NSMutableArray *)getDetailSourceWithElement:(TBXMLElement *)elements {
-    NSMutableArray *messageArray = [NSMutableArray array];
-    TBXMLElement *sub_elem = elements->firstChild;
-    NSString *name = [TBXML elementName:sub_elem];
-    BOOL isElement = [name isEqualToString:@"element"];
-    
-    do {
-        
-        NSMutableDictionary *valueDic = [NSMutableDictionary dictionary];
-        if (isElement) {
-            NSString *elemId = [TBXML valueOfAttributeNamed:@"id" forElement:sub_elem];
-            [valueDic setValue:elemId forKey:@"id"];
-            
-            double positionX = [[TBXML valueOfAttributeNamed:@"x" forElement:sub_elem] doubleValue];
-            [valueDic setValue:@(positionX) forKey:@"x"];
-            double positionY = [[TBXML valueOfAttributeNamed:@"y" forElement:sub_elem] doubleValue];
-            [valueDic setValue:@(positionY) forKey:@"y"];
-            
-            double width = [[TBXML valueOfAttributeNamed:@"sx" forElement:sub_elem] doubleValue];
-            [valueDic setValue:@(width) forKey:@"sx"];
-            double height = [[TBXML valueOfAttributeNamed:@"sy" forElement:sub_elem] doubleValue];
-            [valueDic setValue:@(height) forKey:@"sy"];
-            
-            NSInteger pageIndex = [[TBXML valueOfAttributeNamed:@"page" forElement:sub_elem] doubleValue];
-            [valueDic setValue:@(pageIndex) forKey:@"page"];
-        }
-        else {
-            NSInteger position = [[TBXML valueOfAttributeNamed:@"position" forElement:sub_elem] integerValue];
-            [valueDic setValue:@(position) forKey:@"position"];
-        }
-        [messageArray addObject:valueDic];
-        
-        sub_elem = sub_elem->nextSibling;
-        if (sub_elem == nil) {
-            break;
-        }
-    } while (YES);
-    
-    return messageArray;
-}
-
-
-@end

+ 0 - 76
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/SubjectFinger.plist

@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>2</key>
-	<dict>
-		<key>vertical</key>
-		<false/>
-		<key>name</key>
-		<string>flute</string>
-	</dict>
-	<key>4</key>
-	<dict>
-		<key>vertical</key>
-		<true/>
-		<key>name</key>
-		<string>clarinet</string>
-	</dict>
-	<key>5</key>
-	<dict>
-		<key>vertical</key>
-		<true/>
-		<key>name</key>
-		<string>saxophone</string>
-	</dict>
-	<key>6</key>
-	<dict>
-		<key>vertical</key>
-		<true/>
-		<key>name</key>
-		<string>saxophone</string>
-	</dict>
-	<key>12</key>
-	<dict>
-		<key>vertical</key>
-		<false/>
-		<key>name</key>
-		<string>trumpet</string>
-	</dict>
-	<key>13</key>
-	<dict>
-		<key>vertical</key>
-		<true/>
-		<key>name</key>
-		<string>horn</string>
-	</dict>
-	<key>14</key>
-	<dict>
-		<key>vertical</key>
-		<false/>
-		<key>name</key>
-		<string>trombone</string>
-	</dict>
-	<key>15</key>
-	<dict>
-		<key>vertical</key>
-		<true/>
-		<key>name</key>
-		<string>up-bass-horn</string>
-	</dict>
-	<key>17</key>
-	<dict>
-		<key>vertical</key>
-		<true/>
-		<key>name</key>
-		<string>tuba</string>
-	</dict>
-	<key>120</key>
-	<dict>
-		<key>vertical</key>
-		<true/>
-		<key>name</key>
-		<string>piccolo</string>
-	</dict>
-</dict>
-</plist>

+ 0 - 211
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/TBXML.h

@@ -1,211 +0,0 @@
-// ================================================================================================
-//  TBXML.h
-//  Fast processing of XML files
-//
-// ================================================================================================
-//  Created by Tom Bradley on 21/10/2009.
-//  Version 1.5
-//  
-//  Copyright 2012 71Squared All rights reserved.b
-//  
-//  Permission is hereby granted, free of charge, to any person obtaining a copy
-//  of this software and associated documentation files (the "Software"), to deal
-//  in the Software without restriction, including without limitation the rights
-//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-//  copies of the Software, and to permit persons to whom the Software is
-//  furnished to do so, subject to the following conditions:
-//  
-//  The above copyright notice and this permission notice shall be included in
-//  all copies or substantial portions of the Software.
-//  
-//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-//  THE SOFTWARE.
-// ================================================================================================
-#import <Foundation/Foundation.h>
-
-@class TBXML;
-
-
-// ================================================================================================
-//  Error Codes
-// ================================================================================================
-enum TBXMLErrorCodes {
-    D_TBXML_SUCCESS = 0,
-
-    D_TBXML_DATA_NIL,
-    D_TBXML_DECODE_FAILURE,
-    D_TBXML_MEMORY_ALLOC_FAILURE,
-    D_TBXML_FILE_NOT_FOUND_IN_BUNDLE,
-    
-    D_TBXML_ELEMENT_IS_NIL,
-    D_TBXML_ELEMENT_NAME_IS_NIL,
-    D_TBXML_ELEMENT_NOT_FOUND,
-    D_TBXML_ELEMENT_TEXT_IS_NIL,
-    D_TBXML_ATTRIBUTE_IS_NIL,
-    D_TBXML_ATTRIBUTE_NAME_IS_NIL,
-    D_TBXML_ATTRIBUTE_NOT_FOUND,
-    D_TBXML_PARAM_NAME_IS_NIL
-};
-
-
-// ================================================================================================
-//  Defines
-// ================================================================================================
-#define D_TBXML_DOMAIN @"com.71squared.tbxml"
-
-#define MAX_ELEMENTS 100
-#define MAX_ATTRIBUTES 100
-
-#define TBXML_ATTRIBUTE_NAME_START 0
-#define TBXML_ATTRIBUTE_NAME_END 1
-#define TBXML_ATTRIBUTE_VALUE_START 2
-#define TBXML_ATTRIBUTE_VALUE_END 3
-#define TBXML_ATTRIBUTE_CDATA_END 4
-
-// ================================================================================================
-//  Structures
-// ================================================================================================
-
-/** The TBXMLAttribute structure holds information about a single XML attribute. The structure holds the attribute name, value and next sibling attribute. This structure allows us to create a linked list of attributes belonging to a specific element.
- */
-typedef struct _TBXMLAttribute {
-	char * name;
-	char * value;
-	struct _TBXMLAttribute * next;
-} TBXMLAttribute;
-
-
-
-/** The TBXMLElement structure holds information about a single XML element. The structure holds the element name & text along with pointers to the first attribute, parent element, first child element and first sibling element. Using this structure, we can create a linked list of TBXMLElements to map out an entire XML file.
- */
-typedef struct _TBXMLElement {
-	char * name;
-	char * text;
-	
-	TBXMLAttribute * firstAttribute;
-	
-	struct _TBXMLElement * parentElement;
-	
-	struct _TBXMLElement * firstChild;
-	struct _TBXMLElement * currentChild;
-	
-	struct _TBXMLElement * nextSibling;
-	struct _TBXMLElement * previousSibling;
-	
-} TBXMLElement;
-
-/** The TBXMLElementBuffer is a structure that holds a buffer of TBXMLElements. When the buffer of elements is used, an additional buffer is created and linked to the previous one. This allows for efficient memory allocation/deallocation elements.
- */
-typedef struct _TBXMLElementBuffer {
-	TBXMLElement * elements;
-	struct _TBXMLElementBuffer * next;
-	struct _TBXMLElementBuffer * previous;
-} TBXMLElementBuffer;
-
-
-
-/** The TBXMLAttributeBuffer is a structure that holds a buffer of TBXMLAttributes. When the buffer of attributes is used, an additional buffer is created and linked to the previous one. This allows for efficient memeory allocation/deallocation of attributes.
- */
-typedef struct _TBXMLAttributeBuffer {
-	TBXMLAttribute * attributes;
-	struct _TBXMLAttributeBuffer * next;
-	struct _TBXMLAttributeBuffer * previous;
-} TBXMLAttributeBuffer;
-
-
-// ================================================================================================
-//  Block Callbacks
-// ================================================================================================
-typedef void (^TBXMLSuccessBlock)(TBXML *tbxml);
-typedef void (^TBXMLFailureBlock)(TBXML *tbxml, NSError *error);
-typedef void (^TBXMLIterateBlock)(TBXMLElement *element);
-typedef void (^TBXMLIterateAttributeBlock)(TBXMLAttribute *attribute, NSString *attributeName, NSString *attributeValue);
-
-
-// ================================================================================================
-//  TBXML Public Interface
-// ================================================================================================
-
-@interface TBXML : NSObject {
-	
-@private
-	TBXMLElement * rootXMLElement;
-	
-	TBXMLElementBuffer * currentElementBuffer;
-	TBXMLAttributeBuffer * currentAttributeBuffer;
-	
-	long currentElement;
-	long currentAttribute;
-	
-	char * bytes;
-	long bytesLength;
-}
-
-
-@property (nonatomic, readonly) TBXMLElement * rootXMLElement;
-
-+ (id)newTBXMLWithXMLString:(NSString*)aXMLString error:(NSError **)error;
-+ (id)newTBXMLWithXMLData:(NSData*)aData error:(NSError **)error;
-+ (id)newTBXMLWithXMLFile:(NSString*)aXMLFile error:(NSError **)error;
-+ (id)newTBXMLWithXMLFile:(NSString*)aXMLFile fileExtension:(NSString*)aFileExtension error:(NSError **)error;
-
-+ (id)newTBXMLWithXMLString:(NSString*)aXMLString __attribute__((deprecated));
-+ (id)newTBXMLWithXMLData:(NSData*)aData __attribute__((deprecated));
-+ (id)newTBXMLWithXMLFile:(NSString*)aXMLFile __attribute__((deprecated));
-+ (id)newTBXMLWithXMLFile:(NSString*)aXMLFile fileExtension:(NSString*)aFileExtension __attribute__((deprecated));
-
-
-- (id)initWithXMLString:(NSString*)aXMLString error:(NSError **)error;
-- (id)initWithXMLData:(NSData*)aData error:(NSError **)error;
-- (id)initWithXMLFile:(NSString*)aXMLFile error:(NSError **)error;
-- (id)initWithXMLFile:(NSString*)aXMLFile fileExtension:(NSString*)aFileExtension error:(NSError **)error;
-
-- (id)initWithXMLString:(NSString*)aXMLString __attribute__((deprecated));
-- (id)initWithXMLData:(NSData*)aData __attribute__((deprecated));
-- (id)initWithXMLFile:(NSString*)aXMLFile __attribute__((deprecated));
-- (id)initWithXMLFile:(NSString*)aXMLFile fileExtension:(NSString*)aFileExtension __attribute__((deprecated));
-
-
-- (int) decodeData:(NSData*)data;
-- (int) decodeData:(NSData*)data withError:(NSError **)error;
-
-@end
-
-// ================================================================================================
-//  TBXML Static Functions Interface
-// ================================================================================================
-
-@interface TBXML (StaticFunctions)
-
-+ (NSString*) elementName:(TBXMLElement*)aXMLElement;
-+ (NSString*) elementName:(TBXMLElement*)aXMLElement error:(NSError **)error;
-+ (NSString*) textForElement:(TBXMLElement*)aXMLElement;
-+ (NSString*) textForElement:(TBXMLElement*)aXMLElement error:(NSError **)error;
-+ (NSString*) valueOfAttributeNamed:(NSString *)aName forElement:(TBXMLElement*)aXMLElement;
-+ (NSString*) valueOfAttributeNamed:(NSString *)aName forElement:(TBXMLElement*)aXMLElement error:(NSError **)error;
-
-+ (NSString*) attributeName:(TBXMLAttribute*)aXMLAttribute;
-+ (NSString*) attributeName:(TBXMLAttribute*)aXMLAttribute error:(NSError **)error;
-+ (NSString*) attributeValue:(TBXMLAttribute*)aXMLAttribute;
-+ (NSString*) attributeValue:(TBXMLAttribute*)aXMLAttribute error:(NSError **)error;
-
-+ (TBXMLElement*) nextSiblingNamed:(NSString*)aName searchFromElement:(TBXMLElement*)aXMLElement;
-+ (TBXMLElement*) childElementNamed:(NSString*)aName parentElement:(TBXMLElement*)aParentXMLElement;
-
-+ (TBXMLElement*) nextSiblingNamed:(NSString*)aName searchFromElement:(TBXMLElement*)aXMLElement error:(NSError **)error;
-+ (TBXMLElement*) childElementNamed:(NSString*)aName parentElement:(TBXMLElement*)aParentXMLElement error:(NSError **)error;
-
-/** Iterate through all elements found using query.
- 
- Inspiration taken from John Blanco's RaptureXML https://github.com/ZaBlanc/RaptureXML
- */
-+ (void)iterateElementsForQuery:(NSString *)query fromElement:(TBXMLElement *)anElement withBlock:(TBXMLIterateBlock)iterateBlock;
-+ (void)iterateAttributesOfElement:(TBXMLElement *)anElement withBlock:(TBXMLIterateAttributeBlock)iterateBlock;
-
-
-@end

+ 0 - 952
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/Model/TBXML.m

@@ -1,952 +0,0 @@
-// ================================================================================================
-//  TBXML.m
-//  Fast processing of XML files
-//
-// ================================================================================================
-//  Created by Tom Bradley on 21/10/2009.
-//  Version 1.5
-//  
-//  Copyright 2012 71Squared All rights reserved.
-//  
-//  Permission is hereby granted, free of charge, to any person obtaining a copy
-//  of this software and associated documentation files (the "Software"), to deal
-//  in the Software without restriction, including without limitation the rights
-//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-//  copies of the Software, and to permit persons to whom the Software is
-//  furnished to do so, subject to the following conditions:
-//  
-//  The above copyright notice and this permission notice shall be included in
-//  all copies or substantial portions of the Software.
-//  
-//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-//  THE SOFTWARE.
-// ================================================================================================
-#import "TBXML.h"
-
-// ================================================================================================
-// Private methods
-// ================================================================================================
-@interface TBXML (Private)
-+ (NSString *) errorTextForCode:(int)code;
-+ (NSError *) errorWithCode:(int)code;
-+ (NSError *) errorWithCode:(int)code userInfo:(NSDictionary *)userInfo;
-- (void) decodeBytes;
-- (int) allocateBytesOfLength:(long)length error:(NSError **)error;
-- (TBXMLElement*) nextAvailableElement;
-- (TBXMLAttribute*) nextAvailableAttribute;
-@end
-
-// ================================================================================================
-// Public Implementation
-// ================================================================================================
-@implementation TBXML
-
-@synthesize rootXMLElement;
-
-+ (id)newTBXMLWithXMLString:(NSString*)aXMLString {
-	return [[TBXML alloc] initWithXMLString:aXMLString];
-}
-
-+ (id)newTBXMLWithXMLString:(NSString*)aXMLString error:(NSError *__autoreleasing *)error {
-	return [[TBXML alloc] initWithXMLString:aXMLString error:error];
-}
-
-+ (id)newTBXMLWithXMLData:(NSData*)aData {
-	return [[TBXML alloc] initWithXMLData:aData];
-}
-
-+ (id)newTBXMLWithXMLData:(NSData*)aData error:(NSError *__autoreleasing *)error {
-	return [[TBXML alloc] initWithXMLData:aData error:error];
-}
-
-+ (id)newTBXMLWithXMLFile:(NSString*)aXMLFile {
-	return [[TBXML alloc] initWithXMLFile:aXMLFile];
-}
-
-+ (id)newTBXMLWithXMLFile:(NSString*)aXMLFile error:(NSError *__autoreleasing *)error {
-	return [[TBXML alloc] initWithXMLFile:aXMLFile error:error];
-}
-
-+ (id)newTBXMLWithXMLFile:(NSString*)aXMLFile fileExtension:(NSString*)aFileExtension {
-	return [[TBXML alloc] initWithXMLFile:aXMLFile fileExtension:aFileExtension];
-}
-
-+ (id)newTBXMLWithXMLFile:(NSString*)aXMLFile fileExtension:(NSString*)aFileExtension error:(NSError *__autoreleasing *)error {
-	return [[TBXML alloc] initWithXMLFile:aXMLFile fileExtension:aFileExtension error:error];
-}
-
-- (id)init {
-	self = [super init];
-	if (self != nil) {
-		rootXMLElement = nil;
-		
-		currentElementBuffer = 0;
-		currentAttributeBuffer = 0;
-		
-		currentElement = 0;
-		currentAttribute = 0;		
-		
-		bytes = 0;
-		bytesLength = 0;
-	}
-	return self;
-}
-- (id)initWithXMLString:(NSString*)aXMLString {
-    NSError *error = nil;
-    return [self initWithXMLString:aXMLString error:&error];
-}
-
-- (id)initWithXMLString:(NSString*)aXMLString error:(NSError *__autoreleasing *)error {
-	self = [self init];
-	if (self != nil) {
-		
-        
-        // allocate memory for byte array
-        int result = [self allocateBytesOfLength:[aXMLString lengthOfBytesUsingEncoding:NSUTF8StringEncoding] error:error];
-        
-        // if an error occured, return
-        if (result != D_TBXML_SUCCESS) 
-            return self;
-        
-		// copy string to byte array
-		[aXMLString getBytes:bytes maxLength:bytesLength usedLength:0 encoding:NSUTF8StringEncoding options:NSStringEncodingConversionAllowLossy range:NSMakeRange(0, bytesLength) remainingRange:nil];
-		
-		// set null terminator at end of byte array
-		bytes[bytesLength] = 0;
-		
-		// decode xml data
-		[self decodeBytes];
-        
-        // Check for root element
-        if (error && !*error && !self.rootXMLElement) {
-            *error = [TBXML errorWithCode:D_TBXML_DECODE_FAILURE];
-        }
-	}
-	return self;
-}
-
-- (id)initWithXMLData:(NSData*)aData {
-    NSError *error = nil;
-    return [self initWithXMLData:aData error:&error];
-}
-
-- (id)initWithXMLData:(NSData*)aData error:(NSError **)error {
-    self = [self init];
-    if (self != nil) {
-		// decode aData
-		[self decodeData:aData withError:error];
-    }
-    
-    return self;
-}
-
-- (id)initWithXMLFile:(NSString*)aXMLFile {
-    NSError *error = nil;
-    return [self initWithXMLFile:aXMLFile error:&error];
-}
-
-- (id)initWithXMLFile:(NSString*)aXMLFile error:(NSError **)error {
-    NSString * filename = [aXMLFile stringByDeletingPathExtension];
-    NSString * extension = [aXMLFile pathExtension];
-    
-    self = [self initWithXMLFile:filename fileExtension:extension error:error];
-	if (self != nil) {
-        
-	}
-	return self;
-}
-
-- (id)initWithXMLFile:(NSString*)aXMLFile fileExtension:(NSString*)aFileExtension {
-    NSError *error = nil;
-    return [self initWithXMLFile:aXMLFile fileExtension:aFileExtension error:&error];
-}
-
-- (id)initWithXMLFile:(NSString*)aXMLFile fileExtension:(NSString*)aFileExtension error:(NSError **)error {
-	self = [self init];
-	if (self != nil) {
-        
-        NSData * data;
-        
-        // Get the bundle that this class resides in. This allows to load resources from the app bundle when running unit tests.
-        NSString * bundlePath = [[NSBundle bundleForClass:[self class]] pathForResource:aXMLFile ofType:aFileExtension];
-
-        if (!bundlePath) {
-            if (error) {
-                NSDictionary * userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[aXMLFile stringByAppendingPathExtension:aFileExtension], NSFilePathErrorKey, nil];
-                *error = [TBXML errorWithCode:D_TBXML_FILE_NOT_FOUND_IN_BUNDLE userInfo:userInfo];
-            }
-        } else {
-            SEL dataWithUncompressedContentsOfFile = NSSelectorFromString(@"dataWithUncompressedContentsOfFile:");
-            
-            // Get uncompressed file contents if TBXML+Compression has been included
-            if ([[NSData class] respondsToSelector:dataWithUncompressedContentsOfFile]) {
-                
-                #pragma clang diagnostic push
-                #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
-                data = [[NSData class] performSelector:dataWithUncompressedContentsOfFile withObject:bundlePath];
-                #pragma clang diagnostic pop   
-
-            } else {
-                data = [NSData dataWithContentsOfFile:bundlePath];
-            }
-            
-            // decode data
-            [self decodeData:data withError:error];
-            
-            // Check for root element
-            if (error && !*error && !self.rootXMLElement) {
-                *error = [TBXML errorWithCode:D_TBXML_DECODE_FAILURE];
-            }
-        }
-	}
-	return self;
-}
-
-- (int) decodeData:(NSData*)data {
-    NSError *error = nil;
-    return [self decodeData:data withError:&error];
-}
-
-- (int) decodeData:(NSData*)data withError:(NSError **)error {
-    
-    NSError *localError = nil;
-    
-    // allocate memory for byte array
-    int result = [self allocateBytesOfLength:[data length] error:&localError];
-
-    // ensure no errors during allocation
-    if (result == D_TBXML_SUCCESS) {
-        
-        // copy data to byte array
-        [data getBytes:bytes length:bytesLength];
-        
-        // set null terminator at end of byte array
-        bytes[bytesLength] = 0;
-        
-        // decode xml data
-        [self decodeBytes];
-        
-        if (!self.rootXMLElement) {
-            localError = [TBXML errorWithCode:D_TBXML_DECODE_FAILURE];
-        }
-    }
-
-    // assign local error to pointer
-    if (error) *error = localError;
-    
-    // return success or error code
-    return localError == nil ? D_TBXML_SUCCESS : [localError code];
-}
-
-@end
-
-
-// ================================================================================================
-// Static Functions Implementation
-// ================================================================================================
-
-#pragma mark -
-#pragma mark Static Functions implementation
-
-@implementation TBXML (StaticFunctions)
-
-+ (NSString*) elementName:(TBXMLElement*)aXMLElement {
-	if (nil == aXMLElement->name) return @"";
-	return [NSString stringWithCString:&aXMLElement->name[0] encoding:NSUTF8StringEncoding];
-}
-
-+ (NSString*) elementName:(TBXMLElement*)aXMLElement error:(NSError **)error {
-    // check for nil element
-    if (nil == aXMLElement) {
-        if (error) *error = [TBXML errorWithCode:D_TBXML_ELEMENT_IS_NIL];
-        return @"";
-    }
-    
-    // check for nil element name
-    if (nil == aXMLElement->name || strlen(aXMLElement->name) == 0) {
-        if (error) *error = [TBXML errorWithCode:D_TBXML_ELEMENT_NAME_IS_NIL];
-        return @"";
-    }
-    
-	return [NSString stringWithCString:&aXMLElement->name[0] encoding:NSUTF8StringEncoding];
-}
-
-+ (NSString*) attributeName:(TBXMLAttribute*)aXMLAttribute {
-	if (nil == aXMLAttribute->name) return @"";
-	return [NSString stringWithCString:&aXMLAttribute->name[0] encoding:NSUTF8StringEncoding];
-}
-
-+ (NSString*) attributeName:(TBXMLAttribute*)aXMLAttribute error:(NSError **)error {
-    // check for nil attribute
-    if (nil == aXMLAttribute) {
-        if (error) *error = [TBXML errorWithCode:D_TBXML_ATTRIBUTE_IS_NIL];
-        return @"";
-    }
-    
-    // check for nil attribute name
-    if (nil == aXMLAttribute->name) {
-        if (error) *error = [TBXML errorWithCode:D_TBXML_ATTRIBUTE_NAME_IS_NIL];
-        return @"";
-    }
-    
-	return [NSString stringWithCString:&aXMLAttribute->name[0] encoding:NSUTF8StringEncoding];
-}
-
-
-+ (NSString*) attributeValue:(TBXMLAttribute*)aXMLAttribute {
-	if (nil == aXMLAttribute->value) return @"";
-	return [NSString stringWithCString:&aXMLAttribute->value[0] encoding:NSUTF8StringEncoding];
-}
-
-+ (NSString*) attributeValue:(TBXMLAttribute*)aXMLAttribute error:(NSError **)error {
-    // check for nil attribute
-    if (nil == aXMLAttribute) {
-        if (error) *error = [TBXML errorWithCode:D_TBXML_ATTRIBUTE_IS_NIL];
-        return @"";
-    }
-    
-	return [NSString stringWithCString:&aXMLAttribute->value[0] encoding:NSUTF8StringEncoding];
-}
-
-+ (NSString*) textForElement:(TBXMLElement*)aXMLElement {
-	if (nil == aXMLElement->text) return @"";
-	return [NSString stringWithCString:&aXMLElement->text[0] encoding:NSUTF8StringEncoding];
-}
-
-+ (NSString*) textForElement:(TBXMLElement*)aXMLElement error:(NSError **)error {
-    // check for nil element
-    if (nil == aXMLElement) {
-        if (error) *error = [TBXML errorWithCode:D_TBXML_ELEMENT_IS_NIL];
-        return @"";
-    }
-    
-    // check for nil text value
-    if (nil == aXMLElement->text || strlen(aXMLElement->text) == 0) {
-        if (error) *error = [TBXML errorWithCode:D_TBXML_ELEMENT_TEXT_IS_NIL];
-        return @"";
-    }
-    
-	return [NSString stringWithCString:&aXMLElement->text[0] encoding:NSUTF8StringEncoding];
-}
-
-+ (NSString*) valueOfAttributeNamed:(NSString *)aName forElement:(TBXMLElement*)aXMLElement {
-	const char * name = [aName cStringUsingEncoding:NSUTF8StringEncoding];
-	NSString * value = nil;
-	TBXMLAttribute * attribute = aXMLElement->firstAttribute;
-	while (attribute) {
-		if (strlen(attribute->name) == strlen(name) && memcmp(attribute->name,name,strlen(name)) == 0) {
-			value = [NSString stringWithCString:&attribute->value[0] encoding:NSUTF8StringEncoding];
-			break;
-		}
-		attribute = attribute->next;
-	}
-	return value;
-}
-
-+ (NSString*) valueOfAttributeNamed:(NSString *)aName forElement:(TBXMLElement*)aXMLElement error:(NSError **)error {
-    // check for nil element
-    if (nil == aXMLElement) {
-        if (error) *error = [TBXML errorWithCode:D_TBXML_ELEMENT_IS_NIL];
-        return @"";
-    }
-    
-    // check for nil name parameter
-    if (nil == aName) {
-        if (error) *error = [TBXML errorWithCode:D_TBXML_ATTRIBUTE_NAME_IS_NIL];
-        return @"";
-    }
-    
-	const char * name = [aName cStringUsingEncoding:NSUTF8StringEncoding];
-	NSString * value = nil;
-    
-	TBXMLAttribute * attribute = aXMLElement->firstAttribute;
-	while (attribute) {
-		if (strlen(attribute->name) == strlen(name) && memcmp(attribute->name,name,strlen(name)) == 0) {
-            if (attribute->value[0])
-                value = [NSString stringWithCString:&attribute->value[0] encoding:NSUTF8StringEncoding];
-            else
-                value = [NSString stringWithString:@""];
-            
-			break;
-		}
-		attribute = attribute->next;
-	}
-    
-    // check for attribute not found
-    if (!value) {
-        if (error) *error = [TBXML errorWithCode:D_TBXML_ATTRIBUTE_NOT_FOUND];
-        return @"";
-    }
-    
-	return value;
-}
-
-+ (TBXMLElement*) childElementNamed:(NSString*)aName parentElement:(TBXMLElement*)aParentXMLElement{
-    
-	TBXMLElement * xmlElement = aParentXMLElement->firstChild;
-	const char * name = [aName cStringUsingEncoding:NSUTF8StringEncoding];
-	while (xmlElement) {
-		if (strlen(xmlElement->name) == strlen(name) && memcmp(xmlElement->name,name,strlen(name)) == 0) {
-			return xmlElement;
-		}
-		xmlElement = xmlElement->nextSibling;
-	}
-	return nil;
-}
-
-+ (TBXMLElement*) childElementNamed:(NSString*)aName parentElement:(TBXMLElement*)aParentXMLElement error:(NSError **)error {
-    // check for nil element
-    if (nil == aParentXMLElement) {
-        if (error) *error = [TBXML errorWithCode:D_TBXML_ELEMENT_IS_NIL];
-        return nil;
-    }
-    
-    // check for nil name parameter
-    if (nil == aName) {
-        if (error) *error = [TBXML errorWithCode:D_TBXML_PARAM_NAME_IS_NIL];
-        return nil;
-    }
-    
-	TBXMLElement * xmlElement = aParentXMLElement->firstChild;
-	const char * name = [aName cStringUsingEncoding:NSUTF8StringEncoding];
-	while (xmlElement) {
-		if (strlen(xmlElement->name) == strlen(name) && memcmp(xmlElement->name,name,strlen(name)) == 0) {
-			return xmlElement;
-		}
-		xmlElement = xmlElement->nextSibling;
-	}
-    
-    if (error) *error = [TBXML errorWithCode:D_TBXML_ELEMENT_NOT_FOUND];
-    
-	return nil;
-}
-
-+ (TBXMLElement*) nextSiblingNamed:(NSString*)aName searchFromElement:(TBXMLElement*)aXMLElement{
-	TBXMLElement * xmlElement = aXMLElement->nextSibling;
-	const char * name = [aName cStringUsingEncoding:NSUTF8StringEncoding];
-	while (xmlElement) {
-		if (strlen(xmlElement->name) == strlen(name) && memcmp(xmlElement->name,name,strlen(name)) == 0) {
-			return xmlElement;
-		}
-		xmlElement = xmlElement->nextSibling;
-	}
-	return nil;
-}
-
-+ (TBXMLElement*) nextSiblingNamed:(NSString*)aName searchFromElement:(TBXMLElement*)aXMLElement error:(NSError **)error {
-    // check for nil element
-    if (nil == aXMLElement) {
-        if (error) *error = [TBXML errorWithCode:D_TBXML_ELEMENT_IS_NIL];
-        return nil;
-    }
-    
-    // check for nil name parameter
-    if (nil == aName) {
-        if (error) *error = [TBXML errorWithCode:D_TBXML_PARAM_NAME_IS_NIL];
-        return nil;
-    }
-    
-	TBXMLElement * xmlElement = aXMLElement->nextSibling;
-	const char * name = [aName cStringUsingEncoding:NSUTF8StringEncoding];
-	while (xmlElement) {
-		if (strlen(xmlElement->name) == strlen(name) && memcmp(xmlElement->name,name,strlen(name)) == 0) {
-			return xmlElement;
-		}
-		xmlElement = xmlElement->nextSibling;
-	}
-    
-    if (error) *error = [TBXML errorWithCode:D_TBXML_ELEMENT_NOT_FOUND];
-    
-	return nil;
-}
-
-+ (void)iterateElementsForQuery:(NSString *)query fromElement:(TBXMLElement *)anElement withBlock:(TBXMLIterateBlock)iterateBlock {
-    
-    NSArray *components = [query componentsSeparatedByString:@"."];
-    TBXMLElement *currTBXMLElement = anElement;
-    
-    // navigate down
-    for (NSInteger i=0; i < components.count; ++i) {
-        NSString *iTagName = [components objectAtIndex:i];
-        
-        if ([iTagName isEqualToString:@"*"]) {
-            currTBXMLElement = currTBXMLElement->firstChild;
-            
-            // different behavior depending on if this is the end of the query or midstream
-            if (i < (components.count - 1)) {
-                // midstream
-                do {
-                    NSString *restOfQuery = [[components subarrayWithRange:NSMakeRange(i + 1, components.count - i - 1)] componentsJoinedByString:@"."];
-                    [TBXML iterateElementsForQuery:restOfQuery fromElement:currTBXMLElement withBlock:iterateBlock];
-                } while ((currTBXMLElement = currTBXMLElement->nextSibling));
-                
-            }
-        } else {
-            currTBXMLElement = [TBXML childElementNamed:iTagName parentElement:currTBXMLElement];            
-        }
-        
-        if (!currTBXMLElement) {
-            break;
-        }
-    }
-    
-    if (currTBXMLElement) {
-        // enumerate
-        NSString *childTagName = [components lastObject];
-        
-        if ([childTagName isEqualToString:@"*"]) {
-            childTagName = nil;
-        }
-        
-        do {
-            iterateBlock(currTBXMLElement);
-        } while (childTagName ? (currTBXMLElement = [TBXML nextSiblingNamed:childTagName searchFromElement:currTBXMLElement]) : (currTBXMLElement = currTBXMLElement->nextSibling));
-    }
-}
-
-+ (void)iterateAttributesOfElement:(TBXMLElement *)anElement withBlock:(TBXMLIterateAttributeBlock)iterateAttributeBlock {
-
-    // Obtain first attribute from element
-    TBXMLAttribute * attribute = anElement->firstAttribute;
-    
-    // if attribute is valid
-    
-    while (attribute) {
-        // Call the iterateAttributeBlock with the attribute, it's name and value
-        iterateAttributeBlock(attribute, [TBXML attributeName:attribute], [TBXML attributeValue:attribute]);
-        
-        // Obtain the next attribute
-        attribute = attribute->next;
-    }
-}
-
-@end
-
-
-// ================================================================================================
-// Private Implementation
-// ================================================================================================
-
-#pragma mark -
-#pragma mark Private implementation
-
-@implementation TBXML (Private)
-
-+ (NSString *) errorTextForCode:(int)code {
-    NSString * codeText = @"";
-    
-    switch (code) {
-        case D_TBXML_DATA_NIL:                  codeText = @"Data is nil";                          break;
-        case D_TBXML_DECODE_FAILURE:            codeText = @"Decode failure";                       break;
-        case D_TBXML_MEMORY_ALLOC_FAILURE:      codeText = @"Unable to allocate memory";            break;
-        case D_TBXML_FILE_NOT_FOUND_IN_BUNDLE:  codeText = @"File not found in bundle";             break;
-            
-        case D_TBXML_ELEMENT_IS_NIL:            codeText = @"Element is nil";                       break;
-        case D_TBXML_ELEMENT_NAME_IS_NIL:       codeText = @"Element name is nil";                  break;
-        case D_TBXML_ATTRIBUTE_IS_NIL:          codeText = @"Attribute is nil";                     break;
-        case D_TBXML_ATTRIBUTE_NAME_IS_NIL:     codeText = @"Attribute name is nil";                break;
-        case D_TBXML_ELEMENT_TEXT_IS_NIL:       codeText = @"Element text is nil";                  break;
-        case D_TBXML_PARAM_NAME_IS_NIL:         codeText = @"Parameter name is nil";                break;
-        case D_TBXML_ATTRIBUTE_NOT_FOUND:       codeText = @"Attribute not found";                  break;
-        case D_TBXML_ELEMENT_NOT_FOUND:         codeText = @"Element not found";                    break;
-            
-        default: codeText = @"No Error Description!"; break;
-    }
-    
-    return codeText;
-}
-
-+ (NSError *) errorWithCode:(int)code {
-    
-    NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[TBXML errorTextForCode:code], NSLocalizedDescriptionKey, nil];
-    
-    return [NSError errorWithDomain:D_TBXML_DOMAIN 
-                               code:code 
-                           userInfo:userInfo];
-}
-
-+ (NSError *) errorWithCode:(int)code userInfo:(NSMutableDictionary *)someUserInfo {
-    
-    NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:someUserInfo];
-    [userInfo setValue:[TBXML errorTextForCode:code] forKey:NSLocalizedDescriptionKey];
-    
-    return [NSError errorWithDomain:D_TBXML_DOMAIN 
-                               code:code 
-                           userInfo:userInfo];
-}
-
-- (int) allocateBytesOfLength:(long)length error:(NSError **)error {
-    bytesLength = length;
-    
-    NSError *localError = nil;
-    
-    if(!length) {
-        localError = [TBXML errorWithCode:D_TBXML_DATA_NIL];
-    }
-    
-	bytes = malloc(bytesLength+1);
-    
-    if(!bytes) {
-        localError = [TBXML errorWithCode:D_TBXML_MEMORY_ALLOC_FAILURE];
-    }
-    
-    if (error) *error = localError;
-        
-    return localError == nil ? D_TBXML_SUCCESS : [localError code];
-}
-
-- (void) decodeBytes {
-	
-	// -----------------------------------------------------------------------------
-	// Process xml
-	// -----------------------------------------------------------------------------
-	
-	// set elementStart pointer to the start of our xml
-	char * elementStart=bytes;
-	
-	// set parent element to nil
-	TBXMLElement * parentXMLElement = nil;
-	
-	// find next element start
-	while ((elementStart = strstr(elementStart,"<"))) {
-		
-		// detect comment section
-		if (strncmp(elementStart,"<!--",4) == 0) {
-			elementStart = strstr(elementStart,"-->") + 3;
-			continue;
-		}
-
-		// detect cdata section within element text
-		int isCDATA = strncmp(elementStart,"<![CDATA[",9);
-		
-		// if cdata section found, skip data within cdata section and remove cdata tags
-		if (isCDATA==0) {
-			
-			// find end of cdata section
-			char * CDATAEnd = strstr(elementStart,"]]>");
-			
-			// find start of next element skipping any cdata sections within text
-			char * elementEnd = CDATAEnd;
-			
-			// find next open tag
-			elementEnd = strstr(elementEnd,"<");
-			// if open tag is a cdata section
-			while (strncmp(elementEnd,"<![CDATA[",9) == 0) {
-				// find end of cdata section
-				elementEnd = strstr(elementEnd,"]]>");
-				// find next open tag
-				elementEnd = strstr(elementEnd,"<");
-			}
-			
-			// calculate length of cdata content
-			long CDATALength = CDATAEnd-elementStart;
-			
-			// calculate total length of text
-			long textLength = elementEnd-elementStart;
-			
-			// remove begining cdata section tag
-			memcpy(elementStart, elementStart+9, CDATAEnd-elementStart-9);
-
-			// remove ending cdata section tag
-			memcpy(CDATAEnd-9, CDATAEnd+3, textLength-CDATALength-3);
-			
-			// blank out end of text
-			memset(elementStart+textLength-12,' ',12);
-			
-			// set new search start position 
-			elementStart = CDATAEnd-9;
-			continue;
-		}
-		
-		
-		// find element end, skipping any cdata sections within attributes
-		char * elementEnd = elementStart+1;		
-		while ((elementEnd = strpbrk(elementEnd, "<>"))) {
-			if (strncmp(elementEnd,"<![CDATA[",9) == 0) {
-				elementEnd = strstr(elementEnd,"]]>")+3;
-			} else {
-				break;
-			}
-		}
-		
-        if (!elementEnd) break;
-		
-		// null terminate element end
-		if (elementEnd) *elementEnd = 0;
-		
-		// null terminate element start so previous element text doesnt overrun
-		*elementStart = 0;
-		
-		// get element name start
-		char * elementNameStart = elementStart+1;
-		
-		// ignore tags that start with ? or ! unless cdata "<![CDATA"
-		if (*elementNameStart == '?' || (*elementNameStart == '!' && isCDATA != 0)) {
-			elementStart = elementEnd+1;
-			continue;
-		}
-		
-		// ignore attributes/text if this is a closing element
-		if (*elementNameStart == '/') {
-			elementStart = elementEnd+1;
-			if (parentXMLElement) {
-
-				if (parentXMLElement->text) {
-					// trim whitespace from start of text
-					while (isspace(*parentXMLElement->text)) 
-						parentXMLElement->text++;
-					
-					// trim whitespace from end of text
-					char * end = parentXMLElement->text + strlen(parentXMLElement->text)-1;
-					while (end > parentXMLElement->text && isspace(*end)) 
-						*end--=0;
-				}
-				
-				parentXMLElement = parentXMLElement->parentElement;
-				
-				// if parent element has children clear text
-				if (parentXMLElement && parentXMLElement->firstChild)
-					parentXMLElement->text = 0;
-				
-			}
-			continue;
-		}
-		
-		
-		// is this element opening and closing
-		BOOL selfClosingElement = NO;
-		if (*(elementEnd-1) == '/') {
-			selfClosingElement = YES;
-		}
-		
-		
-		// create new xmlElement struct
-		TBXMLElement * xmlElement = [self nextAvailableElement];
-		
-		// set element name
-		xmlElement->name = elementNameStart;
-		
-		// if there is a parent element
-		if (parentXMLElement) {
-			
-			// if this is first child of parent element
-			if (parentXMLElement->currentChild) {
-				// set next child element in list
-				parentXMLElement->currentChild->nextSibling = xmlElement;
-				xmlElement->previousSibling = parentXMLElement->currentChild;
-				
-				parentXMLElement->currentChild = xmlElement;
-				
-				
-			} else {
-				// set first child element
-				parentXMLElement->currentChild = xmlElement;
-				parentXMLElement->firstChild = xmlElement;
-			}
-			
-			xmlElement->parentElement = parentXMLElement;
-		}
-		
-		
-		// in the following xml the ">" is replaced with \0 by elementEnd. 
-		// element may contain no atributes and would return nil while looking for element name end
-		// <tile> 
-		// find end of element name
-		char * elementNameEnd = strpbrk(xmlElement->name," /\n");
-		
-		
-		// if end was found check for attributes
-		if (elementNameEnd) {
-			
-			// null terminate end of elemenet name
-			*elementNameEnd = 0;
-			
-			char * chr = elementNameEnd;
-			char * name = nil;
-			char * value = nil;
-			char * CDATAStart = nil;
-			char * CDATAEnd = nil;
-			TBXMLAttribute * lastXMLAttribute = nil;
-			TBXMLAttribute * xmlAttribute = nil;
-			BOOL singleQuote = NO;
-			
-			int mode = TBXML_ATTRIBUTE_NAME_START;
-			
-			// loop through all characters within element
-			while (chr++ < elementEnd) {
-				
-				switch (mode) {
-					// look for start of attribute name
-					case TBXML_ATTRIBUTE_NAME_START:
-						if (isspace(*chr)) continue;
-						name = chr;
-						mode = TBXML_ATTRIBUTE_NAME_END;
-						break;
-					// look for end of attribute name
-					case TBXML_ATTRIBUTE_NAME_END:
-						if (isspace(*chr) || *chr == '=') {
-							*chr = 0;
-							mode = TBXML_ATTRIBUTE_VALUE_START;
-						}
-						break;
-					// look for start of attribute value
-					case TBXML_ATTRIBUTE_VALUE_START:
-						if (isspace(*chr)) continue;
-						if (*chr == '"' || *chr == '\'') {
-							value = chr+1;
-							mode = TBXML_ATTRIBUTE_VALUE_END;
-							if (*chr == '\'') 
-								singleQuote = YES;
-							else
-								singleQuote = NO;
-						}
-						break;
-					// look for end of attribute value
-					case TBXML_ATTRIBUTE_VALUE_END:
-						if (*chr == '<' && strncmp(chr, "<![CDATA[", 9) == 0) {
-							mode = TBXML_ATTRIBUTE_CDATA_END;
-						}else if ((*chr == '"' && singleQuote == NO) || (*chr == '\'' && singleQuote == YES)) {
-							*chr = 0;
-							
-							// remove cdata section tags
-							while ((CDATAStart = strstr(value, "<![CDATA["))) {
-								
-								// remove begin cdata tag
-								memcpy(CDATAStart, CDATAStart+9, strlen(CDATAStart)-8);
-								
-								// search for end cdata
-								CDATAEnd = strstr(CDATAStart,"]]>");
-								
-								// remove end cdata tag
-								memcpy(CDATAEnd, CDATAEnd+3, strlen(CDATAEnd)-2);
-							}
-							
-							
-							// create new attribute
-							xmlAttribute = [self nextAvailableAttribute];
-							
-							// if this is the first attribute found, set pointer to this attribute on element
-							if (!xmlElement->firstAttribute) xmlElement->firstAttribute = xmlAttribute;
-							// if previous attribute found, link this attribute to previous one
-							if (lastXMLAttribute) lastXMLAttribute->next = xmlAttribute;
-							// set last attribute to this attribute
-							lastXMLAttribute = xmlAttribute;
-
-							// set attribute name & value
-							xmlAttribute->name = name;
-							xmlAttribute->value = value;
-							
-							// clear name and value pointers
-							name = nil;
-							value = nil;
-							
-							// start looking for next attribute
-							mode = TBXML_ATTRIBUTE_NAME_START;
-						}
-						break;
-						// look for end of cdata
-					case TBXML_ATTRIBUTE_CDATA_END:
-						if (*chr == ']') {
-							if (strncmp(chr, "]]>", 3) == 0) {
-								mode = TBXML_ATTRIBUTE_VALUE_END;
-							}
-						}
-						break;						
-					default:
-						break;
-				}
-			}
-		}
-		
-		// if tag is not self closing, set parent to current element
-		if (!selfClosingElement) {
-			// set text on element to element end+1
-			if (*(elementEnd+1) != '>')
-				xmlElement->text = elementEnd+1;
-			
-			parentXMLElement = xmlElement;
-		}
-		
-		// start looking for next element after end of current element
-		elementStart = elementEnd+1;
-	}
-}
-
-// Deallocate used memory
-- (void) dealloc {
-    
-	if (bytes) {
-		free(bytes);
-		bytes = nil;
-	}
-	
-	while (currentElementBuffer) {
-		if (currentElementBuffer->elements)
-			free(currentElementBuffer->elements);
-		
-		if (currentElementBuffer->previous) {
-			currentElementBuffer = currentElementBuffer->previous;
-			free(currentElementBuffer->next);
-		} else {
-			free(currentElementBuffer);
-			currentElementBuffer = 0;
-		}
-	}
-	
-	while (currentAttributeBuffer) {
-		if (currentAttributeBuffer->attributes)
-			free(currentAttributeBuffer->attributes);
-		
-		if (currentAttributeBuffer->previous) {
-			currentAttributeBuffer = currentAttributeBuffer->previous;
-			free(currentAttributeBuffer->next);
-		} else {
-			free(currentAttributeBuffer);
-			currentAttributeBuffer = 0;
-		}
-	}
-}
-
-- (TBXMLElement*) nextAvailableElement {
-	currentElement++;
-	
-	if (!currentElementBuffer) {
-		currentElementBuffer = calloc(1, sizeof(TBXMLElementBuffer));
-		currentElementBuffer->elements = (TBXMLElement*)calloc(1,sizeof(TBXMLElement)*MAX_ELEMENTS);
-		currentElement = 0;
-		rootXMLElement = &currentElementBuffer->elements[currentElement];
-	} else if (currentElement >= MAX_ELEMENTS) {
-		currentElementBuffer->next = calloc(1, sizeof(TBXMLElementBuffer));
-		currentElementBuffer->next->previous = currentElementBuffer;
-		currentElementBuffer = currentElementBuffer->next;
-		currentElementBuffer->elements = (TBXMLElement*)calloc(1,sizeof(TBXMLElement)*MAX_ELEMENTS);
-		currentElement = 0;
-	}
-	
-	return &currentElementBuffer->elements[currentElement];
-}
-
-- (TBXMLAttribute*) nextAvailableAttribute {
-	currentAttribute++;
-	
-	if (!currentAttributeBuffer) {
-		currentAttributeBuffer = calloc(1, sizeof(TBXMLAttributeBuffer));
-		currentAttributeBuffer->attributes = (TBXMLAttribute*)calloc(MAX_ATTRIBUTES,sizeof(TBXMLAttribute));
-		currentAttribute = 0;
-	} else if (currentAttribute >= MAX_ATTRIBUTES) {
-		currentAttributeBuffer->next = calloc(1, sizeof(TBXMLAttributeBuffer));
-		currentAttributeBuffer->next->previous = currentAttributeBuffer;
-		currentAttributeBuffer = currentAttributeBuffer->next;
-		currentAttributeBuffer->attributes = (TBXMLAttribute*)calloc(MAX_ATTRIBUTES,sizeof(TBXMLAttribute));
-		currentAttribute = 0;
-	}
-	
-	return &currentAttributeBuffer->attributes[currentAttribute];
-}
-
-@end

+ 0 - 25
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Channel/TrackChooseView.h

@@ -1,25 +0,0 @@
-//
-//  TrackChooseView.h
-//  StudentDaya
-//
-//  Created by Kyle on 2022/1/21.
-//  Copyright © 2022 DayaMusic. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-typedef void(^ChooseTrackCallback)(NSMutableArray * _Nullable trackNameArray);
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface TrackChooseView : UIView
-
-+ (instancetype)shareInstanceWithFullTrackArray:(NSMutableArray *)trackNameArray;
-
-- (void)chooseTrackCallback:(ChooseTrackCallback)callback;
-
-- (void)showInView:(UIView *)displayView;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 142
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Channel/TrackChooseView.m

@@ -1,142 +0,0 @@
-//
-//  TrackChooseView.m
-//  StudentDaya
-//
-//  Created by Kyle on 2022/1/21.
-//  Copyright © 2022 DayaMusic. All rights reserved.
-//
-
-#import "TrackChooseView.h"
-
-@interface TrackChooseView ()
-
-@property (nonatomic, strong) NSMutableArray *trackNameArray;
-
-@property (nonatomic, strong) NSMutableArray *chooseTrackArray;
-
-@property (nonatomic, strong) NSMutableArray *tempoArray;
-
-@property (nonatomic, strong) UIScrollView *baseScroll;
-
-@property (weak, nonatomic) IBOutlet UIView *contentView;
-
-@property (nonatomic, copy) ChooseTrackCallback callback;
-
-@end
-
-
-@implementation TrackChooseView
-
-+ (instancetype)shareInstanceWithFullTrackArray:(NSMutableArray *)trackNameArray {
-    TrackChooseView *view = [[[NSBundle mainBundle] loadNibNamed:@"TrackChooseView" owner:nil options:nil] firstObject];
-    view.trackNameArray = trackNameArray;
-    view.frame = CGRectMake(0, 0, KLandscapeWidth, KLandscapeHeight);
-    view.backgroundColor = HexRGBAlpha(0x000000, 0.5f);
-    [view displayView];
-    return view;
-}
-
-
-- (void)displayView {
-    self.tempoArray = [NSMutableArray array];
-    self.baseScroll = [[UIScrollView alloc] init];
-    [self addSubview:self.baseScroll];
-    [self.baseScroll mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.left.right.bottom.top.mas_equalTo(self.contentView);
-    }];
-    CGFloat width = 300.0f;
-    CGFloat height = KLandscapeHeight - 64 - 50 - 40;
-    CGFloat space = 10;
-    CGFloat buttonHeight = 30;
-    CGFloat buttonWidth = (width - space * 4) / 3.0f;
-    CGFloat maxHeight = 0;
-    for (NSInteger i = 0; i < self.trackNameArray.count; i++) {
-        CGRect frame = CGRectMake(space + (i % 3) * (buttonWidth + space), (i / 3) * (buttonHeight + space), buttonWidth, buttonHeight);
-        UIButton *button =  [self createButtonWithName:self.trackNameArray[i] frame:frame tag:i+1000];
-        if (i == 0) {
-            button.selected = YES;
-            button.layer.borderColor = THEMECOLOR.CGColor;
-        }
-        [self.baseScroll addSubview:button];
-        maxHeight = (i / 3) * (buttonHeight + space) + buttonHeight + space;
-    }
-    if (height < maxHeight) {
-        height = maxHeight;
-    }
-    self.baseScroll.contentSize = CGSizeMake(width, height);
-    // 默认选择第一个
-    [self.chooseTrackArray addObject:self.trackNameArray[0]];
-    [self.tempoArray addObject:self.trackNameArray[0]];
-}
-
-
-- (UIButton *)createButtonWithName:(NSString *)name frame:(CGRect)frame tag:(NSInteger)tag {
-    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
-    button.frame = frame;
-    button.tag = 1000 + tag;
-    [button setTitle:name forState:UIControlStateNormal];
-    [button addTarget:self action:@selector(buttonClickAction:) forControlEvents:UIControlEventTouchUpInside];
-    button.layer.cornerRadius = 5.0f;
-    button.layer.borderColor = HexRGB(0xf5f5f5).CGColor;
-    button.layer.borderWidth = 1.0f;
-    [button.titleLabel setFont:[UIFont systemFontOfSize:12.0f]];
-    [button setTitleColor:HexRGB(0x333333) forState:UIControlStateNormal];
-    [button setTitleColor:THEMECOLOR forState:UIControlStateSelected];
-    return button;
-}
-
-- (void)buttonClickAction:(UIButton *)sender {
-    sender.selected = !sender.selected;
-    BOOL isSelected = sender.isSelected;
-    NSString *trackName = sender.titleLabel.text;
-    if (isSelected) {
-        sender.layer.borderColor = THEMECOLOR.CGColor;
-        [self chooseTrackWithName:trackName];
-    }
-    else {
-        sender.layer.borderColor = HexRGB(0xf5f5f5).CGColor;
-        [self removeChooseTrackWithName:trackName];
-    }
-}
-- (IBAction)sureAction:(id)sender {
-    if (self.callback) {
-        self.chooseTrackArray = [NSMutableArray arrayWithArray:self.tempoArray];
-        self.callback(self.chooseTrackArray);
-    }
-    [self removeFromSuperview];
-}
-
-- (IBAction)cancleAction:(id)sender {
-    [self hideView];
-}
-
-- (void)hideView {
-    [self removeFromSuperview];
-}
-- (void)chooseTrackWithName:(NSString *)trackName {
-    [self.tempoArray addObject:trackName];
-}
-
-- (void)removeChooseTrackWithName:(NSString *)trackName {
-    [self.tempoArray removeObject:trackName];
-}
-- (void)showInView:(UIView *)displayView {
-    [displayView addSubview:self];
-}
-
-
-- (void)chooseTrackCallback:(ChooseTrackCallback)callback {
-    if (callback) {
-        self.callback = callback;
-    }
-}
-
-/*
-// Only override drawRect: if you perform custom drawing.
-// An empty implementation adversely affects performance during animation.
-- (void)drawRect:(CGRect)rect {
-    // Drawing code
-}
-*/
-
-@end

+ 0 - 113
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Channel/TrackChooseView.xib

@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
-    <device id="retina6_1" orientation="portrait" appearance="light"/>
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
-        <capability name="System colors in document resources" minToolsVersion="11.0"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <objects>
-        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
-        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="TrackChooseView">
-            <rect key="frame" x="0.0" y="0.0" width="750" height="375"/>
-            <autoresizingMask key="autoresizingMask"/>
-            <subviews>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="eNR-CP-hMc">
-                    <rect key="frame" x="215" y="32" width="320" height="311"/>
-                    <subviews>
-                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="image_alertTips" translatesAutoresizingMaskIntoConstraints="NO" id="GeC-WM-XZa">
-                            <rect key="frame" x="106" y="-4" width="108" height="31"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="31" id="Vqd-ny-i28"/>
-                                <constraint firstAttribute="width" constant="108" id="fr5-5C-Fjc"/>
-                            </constraints>
-                        </imageView>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="选择乐器" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="jDn-Lm-9Nb">
-                            <rect key="frame" x="127" y="1.5" width="66" height="20"/>
-                            <fontDescription key="fontDescription" type="system" pointSize="16"/>
-                            <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="HLa-gh-ykH">
-                            <rect key="frame" x="10" y="40" width="300" height="221"/>
-                            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                        </view>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="TuA-cX-WJb">
-                            <rect key="frame" x="110" y="271" width="100" height="30"/>
-                            <color key="backgroundColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <constraints>
-                                <constraint firstAttribute="width" constant="100" id="04l-xF-B07"/>
-                                <constraint firstAttribute="height" constant="30" id="Fpt-41-dXV"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" pointSize="16"/>
-                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
-                            <state key="normal" title="确定"/>
-                            <userDefinedRuntimeAttributes>
-                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                    <real key="value" value="15"/>
-                                </userDefinedRuntimeAttribute>
-                            </userDefinedRuntimeAttributes>
-                            <connections>
-                                <action selector="sureAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="Jax-ON-cOH"/>
-                            </connections>
-                        </button>
-                    </subviews>
-                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                    <constraints>
-                        <constraint firstItem="GeC-WM-XZa" firstAttribute="centerX" secondItem="eNR-CP-hMc" secondAttribute="centerX" id="Ac7-xw-CrE"/>
-                        <constraint firstAttribute="width" constant="320" id="FfP-sW-0Os"/>
-                        <constraint firstAttribute="bottom" secondItem="TuA-cX-WJb" secondAttribute="bottom" constant="10" id="MlH-oo-9cl"/>
-                        <constraint firstItem="HLa-gh-ykH" firstAttribute="top" secondItem="eNR-CP-hMc" secondAttribute="top" constant="40" id="ObX-yh-RXp"/>
-                        <constraint firstItem="jDn-Lm-9Nb" firstAttribute="centerX" secondItem="GeC-WM-XZa" secondAttribute="centerX" id="Qqc-ww-Ctv"/>
-                        <constraint firstItem="TuA-cX-WJb" firstAttribute="top" secondItem="HLa-gh-ykH" secondAttribute="bottom" constant="10" id="UfX-Vl-d1X"/>
-                        <constraint firstAttribute="trailing" secondItem="HLa-gh-ykH" secondAttribute="trailing" constant="10" id="YLK-oy-QnV"/>
-                        <constraint firstItem="jDn-Lm-9Nb" firstAttribute="centerY" secondItem="GeC-WM-XZa" secondAttribute="centerY" id="kEM-Ki-Iwi"/>
-                        <constraint firstItem="GeC-WM-XZa" firstAttribute="top" secondItem="eNR-CP-hMc" secondAttribute="top" constant="-4" id="kas-ox-JDL"/>
-                        <constraint firstItem="HLa-gh-ykH" firstAttribute="leading" secondItem="eNR-CP-hMc" secondAttribute="leading" constant="10" id="oob-L8-Acp"/>
-                        <constraint firstItem="TuA-cX-WJb" firstAttribute="centerX" secondItem="eNR-CP-hMc" secondAttribute="centerX" id="vjk-rT-eyj"/>
-                    </constraints>
-                    <userDefinedRuntimeAttributes>
-                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                            <real key="value" value="12"/>
-                        </userDefinedRuntimeAttribute>
-                    </userDefinedRuntimeAttributes>
-                </view>
-                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="91q-38-ktZ">
-                    <rect key="frame" x="535" y="10" width="44" height="44"/>
-                    <constraints>
-                        <constraint firstAttribute="height" constant="44" id="cnq-7T-YJl"/>
-                        <constraint firstAttribute="width" constant="44" id="d4t-p7-m3i"/>
-                    </constraints>
-                    <state key="normal" image="cloud_cancle"/>
-                    <connections>
-                        <action selector="cancleAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="ar1-Sk-D9Q"/>
-                    </connections>
-                </button>
-            </subviews>
-            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-            <constraints>
-                <constraint firstItem="eNR-CP-hMc" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="32" id="NJh-Th-HQW"/>
-                <constraint firstItem="91q-38-ktZ" firstAttribute="centerY" secondItem="eNR-CP-hMc" secondAttribute="top" id="Tqw-hy-1Uc"/>
-                <constraint firstAttribute="bottom" secondItem="eNR-CP-hMc" secondAttribute="bottom" constant="32" id="UxN-d4-lNH"/>
-                <constraint firstItem="91q-38-ktZ" firstAttribute="leading" secondItem="eNR-CP-hMc" secondAttribute="trailing" id="f9i-84-h7Y"/>
-                <constraint firstItem="eNR-CP-hMc" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="lVN-0h-cpf"/>
-            </constraints>
-            <nil key="simulatedTopBarMetrics"/>
-            <nil key="simulatedBottomBarMetrics"/>
-            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
-            <connections>
-                <outlet property="contentView" destination="HLa-gh-ykH" id="1ag-Ko-i22"/>
-            </connections>
-            <point key="canvasLocation" x="195.6521739130435" y="24.107142857142858"/>
-        </view>
-    </objects>
-    <resources>
-        <image name="cloud_cancle" width="26" height="26"/>
-        <image name="image_alertTips" width="108" height="31"/>
-        <systemColor name="systemBackgroundColor">
-            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-        </systemColor>
-    </resources>
-</document>

+ 0 - 23
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Help/CloudFeedbackView.h

@@ -1,23 +0,0 @@
-//
-//  CloudFeedbackView.h
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/15.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-typedef void(^CloudFeedbackCallback)(NSString *content, NSString *type);
-
-@interface CloudFeedbackView : UIView
-
-+ (instancetype)shareInstance;
-
-- (void)submitCallback:(CloudFeedbackCallback)callback;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 126
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Help/CloudFeedbackView.m

@@ -1,126 +0,0 @@
-//
-//  CloudFeedbackView.m
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/15.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import "CloudFeedbackView.h"
-
-@interface CloudFeedbackView ()<UITextViewDelegate>
-@property (weak, nonatomic) IBOutlet UILabel *tipsLabel;
-
-@property (weak, nonatomic) IBOutlet UILabel *countLabel;
-
-@property (weak, nonatomic) IBOutlet UITextView *textView;
-
-@property (nonatomic, copy) CloudFeedbackCallback callback;
-
-@property (nonatomic, strong) NSString *typeString;
-
-@property (nonatomic, assign) NSInteger lastChooseIndex;
-
-@end
-
-
-
-@implementation CloudFeedbackView
-
-- (void)awakeFromNib {
-    [super awakeFromNib];
-    self.textView.delegate = self;
-}
-
-+ (instancetype)shareInstance {
-    CloudFeedbackView *view = [[[NSBundle mainBundle] loadNibNamed:@"CloudFeedbackView" owner:nil options:nil] firstObject];
-    return view;
-}
-
-- (void)submitCallback:(CloudFeedbackCallback)callback {
-    if (callback) {
-        self.callback = callback;
-    }
-}
-
-- (IBAction)TypeButonAction:(UIButton *)sender {
-    [sender setBackgroundColor:HexRGB(0xe2fff9)];
-    sender.layer.borderColor = THEMECOLOR.CGColor;
-    self.typeString = sender.titleLabel.text;
-    NSInteger index = sender.tag;
-    
-    if (index == self.lastChooseIndex || self.lastChooseIndex == 0) {
-        self.lastChooseIndex = index;
-        return;
-    }
-    else {
-        UIButton *preButton = (UIButton *)[self viewWithTag:self.lastChooseIndex];
-        [preButton setBackgroundColor:HexRGB(0x999999)];
-        preButton.layer.borderColor = HexRGB(0xf8f8f8).CGColor;
-        self.lastChooseIndex = index;
-    }
-}
-
-- (IBAction)sureAction:(id)sender {
-    [self endEditing:YES];
-    if (self.callback) {
-        if ([NSString isEmptyString:self.typeString]) {
-            [LOADING_MANAGER MBShowAUTOHidingInWindow:@"请选择问题类型"];
-            return;
-        }
-        else if ([NSString isEmptyString:self.textView.text]) {
-            [LOADING_MANAGER MBShowAUTOHidingInWindow:@"请描述您遇到的问题"];
-            return;
-        }
-        self.callback(self.textView.text, self.typeString);
-    }
-}
-
-#pragma mark   ---- delegate
-
-- (void)textViewDidBeginEditing:(UITextView *)textView {
-    self.tipsLabel.hidden = YES;
-}
-- (void)textViewDidEndEditing:(UITextView *)textView {
-    if ([NSString isEmptyString:textView.text]) {
-        self.tipsLabel.hidden = NO;
-    }
-}
-
-- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
-    if ([text isEqualToString:@"\n"]) {
-        [self endEditing:YES];
-        return YES;
-    }
-    if ([text isEqualToString:@""]) {
-        return YES;
-    }
-    // 输入控制
-    NSString *newString = [textView.text stringByReplacingCharactersInRange:range withString:text];
-    if (newString.length > 200) {
-        return NO;
-    }
-    self.countLabel.text = [NSString stringWithFormat:@"%zd/200", newString.length];
-    return YES;
-}
-
-
-- (BOOL)textViewShouldEndEditing:(UITextView *)textView {
-    [self endEditing:YES];
-    return YES;
-}
-
-- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
-    [self endEditing:YES];
-}
-
-
-/*
-// Only override drawRect: if you perform custom drawing.
-// An empty implementation adversely affects performance during animation.
-- (void)drawRect:(CGRect)rect {
-    // Drawing code
-}
-*/
-
-@end

+ 0 - 325
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Help/CloudFeedbackView.xib

@@ -1,325 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
-    <device id="retina6_1" orientation="portrait" appearance="light"/>
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
-        <capability name="System colors in document resources" minToolsVersion="11.0"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <objects>
-        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
-        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="CloudFeedbackView">
-            <rect key="frame" x="0.0" y="0.0" width="1162" height="515"/>
-            <autoresizingMask key="autoresizingMask"/>
-            <subviews>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0Jt-Nx-mxp">
-                    <rect key="frame" x="421" y="97.5" width="320" height="320"/>
-                    <subviews>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="意见反馈" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="39T-t6-0Wv">
-                            <rect key="frame" x="127.5" y="12" width="65.5" height="22"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="22" id="Ma2-5f-LS5"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
-                            <color key="textColor" red="0.10196078431372549" green="0.10196078431372549" blue="0.10196078431372549" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Gq5-UG-UPH">
-                            <rect key="frame" x="0.0" y="45" width="320" height="1"/>
-                            <color key="backgroundColor" red="0.94117647058823528" green="0.94117647058823528" blue="0.94117647058823528" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="1" id="bXb-3D-Mpu"/>
-                            </constraints>
-                        </view>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="请选择问题类型" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TEQ-Mu-woj">
-                            <rect key="frame" x="18" y="70" width="100" height="20"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="20" id="jjb-5v-wg7"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                            <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <button opaque="NO" tag="1001" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="7U7-1u-Czi">
-                            <rect key="frame" x="18" y="98" width="89.5" height="27"/>
-                            <color key="backgroundColor" red="0.97254901960784312" green="0.97254901960784312" blue="0.97254901960784312" alpha="1" colorSpace="calibratedRGB"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="27" id="mkM-2a-PEa"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" pointSize="12"/>
-                            <state key="normal" title="识别不准">
-                                <color key="titleColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="calibratedRGB"/>
-                            </state>
-                            <userDefinedRuntimeAttributes>
-                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                    <real key="value" value="6"/>
-                                </userDefinedRuntimeAttribute>
-                                <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
-                                    <real key="value" value="1"/>
-                                </userDefinedRuntimeAttribute>
-                                <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
-                                    <color key="value" red="0.97254901960784312" green="0.97254901960784312" blue="0.97254901960784312" alpha="1" colorSpace="calibratedRGB"/>
-                                </userDefinedRuntimeAttribute>
-                            </userDefinedRuntimeAttributes>
-                            <connections>
-                                <action selector="TypeButonAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="zAI-Ki-2V5"/>
-                            </connections>
-                        </button>
-                        <button opaque="NO" tag="1002" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="J1s-eN-oKW">
-                            <rect key="frame" x="115.5" y="98" width="89" height="27"/>
-                            <color key="backgroundColor" red="0.97254901959999995" green="0.97254901959999995" blue="0.97254901959999995" alpha="1" colorSpace="calibratedRGB"/>
-                            <fontDescription key="fontDescription" type="system" pointSize="12"/>
-                            <state key="normal" title="无法评测">
-                                <color key="titleColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="calibratedRGB"/>
-                            </state>
-                            <userDefinedRuntimeAttributes>
-                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                    <real key="value" value="6"/>
-                                </userDefinedRuntimeAttribute>
-                                <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
-                                    <real key="value" value="1"/>
-                                </userDefinedRuntimeAttribute>
-                                <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
-                                    <color key="value" red="0.97254901960784312" green="0.97254901960784312" blue="0.97254901960784312" alpha="1" colorSpace="calibratedRGB"/>
-                                </userDefinedRuntimeAttribute>
-                            </userDefinedRuntimeAttributes>
-                            <connections>
-                                <action selector="TypeButonAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="U77-aX-4ha"/>
-                            </connections>
-                        </button>
-                        <button opaque="NO" tag="1003" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="x52-Ag-qNB">
-                            <rect key="frame" x="212.5" y="98" width="89.5" height="27"/>
-                            <color key="backgroundColor" red="0.97254901959999995" green="0.97254901959999995" blue="0.97254901959999995" alpha="1" colorSpace="calibratedRGB"/>
-                            <fontDescription key="fontDescription" type="system" pointSize="12"/>
-                            <state key="normal" title="不出评测结果">
-                                <color key="titleColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="calibratedRGB"/>
-                            </state>
-                            <userDefinedRuntimeAttributes>
-                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                    <real key="value" value="6"/>
-                                </userDefinedRuntimeAttribute>
-                                <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
-                                    <real key="value" value="1"/>
-                                </userDefinedRuntimeAttribute>
-                                <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
-                                    <color key="value" red="0.97254901960784312" green="0.97254901960784312" blue="0.97254901960784312" alpha="1" colorSpace="calibratedRGB"/>
-                                </userDefinedRuntimeAttribute>
-                            </userDefinedRuntimeAttributes>
-                            <connections>
-                                <action selector="TypeButonAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="pQC-pc-EWq"/>
-                            </connections>
-                        </button>
-                        <button opaque="NO" tag="1004" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1Mw-7R-dLz">
-                            <rect key="frame" x="18" y="134" width="89.5" height="27"/>
-                            <color key="backgroundColor" red="0.97254901959999995" green="0.97254901959999995" blue="0.97254901959999995" alpha="1" colorSpace="calibratedRGB"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="27" id="db0-C7-Pdy"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" pointSize="12"/>
-                            <state key="normal" title="曲谱不一致">
-                                <color key="titleColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="calibratedRGB"/>
-                            </state>
-                            <userDefinedRuntimeAttributes>
-                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                    <real key="value" value="6"/>
-                                </userDefinedRuntimeAttribute>
-                                <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
-                                    <real key="value" value="1"/>
-                                </userDefinedRuntimeAttribute>
-                                <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
-                                    <color key="value" red="0.97254901960784312" green="0.97254901960784312" blue="0.97254901960784312" alpha="1" colorSpace="calibratedRGB"/>
-                                </userDefinedRuntimeAttribute>
-                            </userDefinedRuntimeAttributes>
-                            <connections>
-                                <action selector="TypeButonAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="u1y-qp-4qe"/>
-                            </connections>
-                        </button>
-                        <button opaque="NO" tag="1005" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9DQ-zy-Jq5">
-                            <rect key="frame" x="115.5" y="134" width="89" height="27"/>
-                            <color key="backgroundColor" red="0.97254901959999995" green="0.97254901959999995" blue="0.97254901959999995" alpha="1" colorSpace="calibratedRGB"/>
-                            <fontDescription key="fontDescription" type="system" pointSize="12"/>
-                            <state key="normal" title="指法错误">
-                                <color key="titleColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="calibratedRGB"/>
-                            </state>
-                            <userDefinedRuntimeAttributes>
-                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                    <real key="value" value="6"/>
-                                </userDefinedRuntimeAttribute>
-                                <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
-                                    <real key="value" value="1"/>
-                                </userDefinedRuntimeAttribute>
-                                <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
-                                    <color key="value" red="0.97254901960784312" green="0.97254901960784312" blue="0.97254901960784312" alpha="1" colorSpace="calibratedRGB"/>
-                                </userDefinedRuntimeAttribute>
-                            </userDefinedRuntimeAttributes>
-                            <connections>
-                                <action selector="TypeButonAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="fMv-k4-1rs"/>
-                            </connections>
-                        </button>
-                        <button opaque="NO" tag="1006" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="JzE-X8-lLe">
-                            <rect key="frame" x="212.5" y="134" width="89.5" height="27"/>
-                            <color key="backgroundColor" red="0.97254901959999995" green="0.97254901959999995" blue="0.97254901959999995" alpha="1" colorSpace="calibratedRGB"/>
-                            <fontDescription key="fontDescription" type="system" pointSize="12"/>
-                            <state key="normal" title="其他">
-                                <color key="titleColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="calibratedRGB"/>
-                            </state>
-                            <userDefinedRuntimeAttributes>
-                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                    <real key="value" value="6"/>
-                                </userDefinedRuntimeAttribute>
-                                <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
-                                    <real key="value" value="1"/>
-                                </userDefinedRuntimeAttribute>
-                                <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
-                                    <color key="value" red="0.97254901960784312" green="0.97254901960784312" blue="0.97254901960784312" alpha="1" colorSpace="calibratedRGB"/>
-                                </userDefinedRuntimeAttribute>
-                            </userDefinedRuntimeAttributes>
-                            <connections>
-                                <action selector="TypeButonAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="qB6-4P-wfV"/>
-                            </connections>
-                        </button>
-                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fDw-RL-YZQ">
-                            <rect key="frame" x="20" y="171" width="284" height="71"/>
-                            <subviews>
-                                <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="l1z-4Y-3eT">
-                                    <rect key="frame" x="12" y="10" width="260" height="51"/>
-                                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                                    <color key="textColor" systemColor="labelColor"/>
-                                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                                    <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
-                                </textView>
-                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0/200" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9Jw-La-2Hn">
-                                    <rect key="frame" x="244" y="47" width="34" height="15"/>
-                                    <fontDescription key="fontDescription" type="system" pointSize="12"/>
-                                    <color key="textColor" red="0.80000000000000004" green="0.80000000000000004" blue="0.80000000000000004" alpha="1" colorSpace="calibratedRGB"/>
-                                    <nil key="highlightedColor"/>
-                                </label>
-                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="请详细描述您遇到的问题,以便我们尽快为您解决!" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="nvM-32-Z6W">
-                                    <rect key="frame" x="9" y="15" width="243" height="29"/>
-                                    <fontDescription key="fontDescription" type="system" pointSize="12"/>
-                                    <color key="textColor" red="0.50196078431372548" green="0.50196078431372548" blue="0.50196078431372548" alpha="1" colorSpace="calibratedRGB"/>
-                                    <nil key="highlightedColor"/>
-                                </label>
-                            </subviews>
-                            <color key="backgroundColor" red="0.97254901959999995" green="0.97254901959999995" blue="0.97254901959999995" alpha="1" colorSpace="calibratedRGB"/>
-                            <constraints>
-                                <constraint firstAttribute="trailing" secondItem="l1z-4Y-3eT" secondAttribute="trailing" constant="12" id="DrW-kV-bFE"/>
-                                <constraint firstItem="l1z-4Y-3eT" firstAttribute="top" secondItem="fDw-RL-YZQ" secondAttribute="top" constant="10" id="KKe-Sd-KsV"/>
-                                <constraint firstItem="nvM-32-Z6W" firstAttribute="top" secondItem="fDw-RL-YZQ" secondAttribute="top" constant="15" id="WnD-Kz-gA6"/>
-                                <constraint firstAttribute="bottom" secondItem="9Jw-La-2Hn" secondAttribute="bottom" constant="9" id="Zz7-nb-trk"/>
-                                <constraint firstItem="nvM-32-Z6W" firstAttribute="leading" secondItem="fDw-RL-YZQ" secondAttribute="leading" constant="9" id="aIL-ME-Sir"/>
-                                <constraint firstItem="l1z-4Y-3eT" firstAttribute="leading" secondItem="fDw-RL-YZQ" secondAttribute="leading" constant="12" id="aX5-em-K7L"/>
-                                <constraint firstAttribute="bottom" secondItem="l1z-4Y-3eT" secondAttribute="bottom" constant="10" id="cRb-ik-WSo"/>
-                                <constraint firstAttribute="height" constant="71" id="kLV-hO-8zU"/>
-                                <constraint firstAttribute="trailing" secondItem="nvM-32-Z6W" secondAttribute="trailing" constant="32" id="lNb-ym-wwt"/>
-                                <constraint firstAttribute="trailing" secondItem="9Jw-La-2Hn" secondAttribute="trailing" constant="6" id="y7h-9W-aTe"/>
-                            </constraints>
-                            <userDefinedRuntimeAttributes>
-                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                    <real key="value" value="6"/>
-                                </userDefinedRuntimeAttribute>
-                            </userDefinedRuntimeAttributes>
-                        </view>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="d27-7V-Wg8">
-                            <rect key="frame" x="65" y="274" width="190" height="34"/>
-                            <color key="backgroundColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="calibratedRGB"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="34" id="N3v-Xl-2MW"/>
-                                <constraint firstAttribute="width" constant="190" id="uxK-Vz-uCB"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
-                            <state key="normal" title="提交反馈"/>
-                            <userDefinedRuntimeAttributes>
-                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                    <real key="value" value="17"/>
-                                </userDefinedRuntimeAttribute>
-                            </userDefinedRuntimeAttributes>
-                            <connections>
-                                <action selector="sureAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="jAn-FI-sqc"/>
-                            </connections>
-                        </button>
-                    </subviews>
-                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                    <constraints>
-                        <constraint firstItem="9DQ-zy-Jq5" firstAttribute="leading" secondItem="1Mw-7R-dLz" secondAttribute="trailing" constant="8" id="06O-4g-wue"/>
-                        <constraint firstItem="1Mw-7R-dLz" firstAttribute="leading" secondItem="0Jt-Nx-mxp" secondAttribute="leading" constant="18" id="2WH-8E-XvK"/>
-                        <constraint firstItem="J1s-eN-oKW" firstAttribute="width" secondItem="7U7-1u-Czi" secondAttribute="width" id="32b-GC-Ka1"/>
-                        <constraint firstItem="J1s-eN-oKW" firstAttribute="height" secondItem="7U7-1u-Czi" secondAttribute="height" id="3Pw-Ri-nap"/>
-                        <constraint firstItem="7U7-1u-Czi" firstAttribute="top" secondItem="TEQ-Mu-woj" secondAttribute="bottom" constant="8" id="3R2-EC-nqd"/>
-                        <constraint firstItem="JzE-X8-lLe" firstAttribute="centerY" secondItem="1Mw-7R-dLz" secondAttribute="centerY" id="4Il-Nw-NoN"/>
-                        <constraint firstItem="d27-7V-Wg8" firstAttribute="centerX" secondItem="0Jt-Nx-mxp" secondAttribute="centerX" id="5FM-g1-YxC"/>
-                        <constraint firstItem="39T-t6-0Wv" firstAttribute="centerX" secondItem="0Jt-Nx-mxp" secondAttribute="centerX" id="5e2-4O-Fsp"/>
-                        <constraint firstItem="x52-Ag-qNB" firstAttribute="centerY" secondItem="7U7-1u-Czi" secondAttribute="centerY" id="5lJ-KP-9I0"/>
-                        <constraint firstAttribute="height" constant="320" id="76Q-k0-SSd"/>
-                        <constraint firstItem="7U7-1u-Czi" firstAttribute="leading" secondItem="0Jt-Nx-mxp" secondAttribute="leading" constant="18" id="7c9-x7-KoI"/>
-                        <constraint firstAttribute="trailing" secondItem="fDw-RL-YZQ" secondAttribute="trailing" constant="16" id="HP4-kF-sOC"/>
-                        <constraint firstAttribute="width" constant="320" id="LP9-VX-MX3"/>
-                        <constraint firstAttribute="trailing" secondItem="JzE-X8-lLe" secondAttribute="trailing" constant="18" id="Nz2-Yb-Rlm"/>
-                        <constraint firstItem="Gq5-UG-UPH" firstAttribute="top" secondItem="0Jt-Nx-mxp" secondAttribute="top" constant="45" id="UXl-Ug-AeJ"/>
-                        <constraint firstItem="J1s-eN-oKW" firstAttribute="leading" secondItem="7U7-1u-Czi" secondAttribute="trailing" constant="8" id="W0q-B2-4na"/>
-                        <constraint firstItem="JzE-X8-lLe" firstAttribute="width" secondItem="1Mw-7R-dLz" secondAttribute="width" id="WKN-Wm-9Yd"/>
-                        <constraint firstItem="x52-Ag-qNB" firstAttribute="leading" secondItem="J1s-eN-oKW" secondAttribute="trailing" constant="8" id="aBW-dd-CaO"/>
-                        <constraint firstAttribute="trailing" secondItem="Gq5-UG-UPH" secondAttribute="trailing" id="c0O-mK-lEW"/>
-                        <constraint firstItem="fDw-RL-YZQ" firstAttribute="leading" secondItem="0Jt-Nx-mxp" secondAttribute="leading" constant="20" id="d4z-sv-jem"/>
-                        <constraint firstItem="x52-Ag-qNB" firstAttribute="height" secondItem="7U7-1u-Czi" secondAttribute="height" id="ebh-5Z-mfM"/>
-                        <constraint firstItem="JzE-X8-lLe" firstAttribute="height" secondItem="1Mw-7R-dLz" secondAttribute="height" id="fn9-T1-lqv"/>
-                        <constraint firstItem="Gq5-UG-UPH" firstAttribute="leading" secondItem="0Jt-Nx-mxp" secondAttribute="leading" id="iGf-AP-6wJ"/>
-                        <constraint firstItem="9DQ-zy-Jq5" firstAttribute="height" secondItem="1Mw-7R-dLz" secondAttribute="height" id="j2F-03-fR7"/>
-                        <constraint firstItem="fDw-RL-YZQ" firstAttribute="top" secondItem="1Mw-7R-dLz" secondAttribute="bottom" constant="10" id="kke-Er-EGE"/>
-                        <constraint firstItem="TEQ-Mu-woj" firstAttribute="top" secondItem="Gq5-UG-UPH" secondAttribute="bottom" constant="24" id="l9h-eX-tM7"/>
-                        <constraint firstItem="TEQ-Mu-woj" firstAttribute="leading" secondItem="0Jt-Nx-mxp" secondAttribute="leading" constant="18" id="mbH-Py-0kV"/>
-                        <constraint firstAttribute="bottom" secondItem="d27-7V-Wg8" secondAttribute="bottom" constant="12" id="meP-fV-07D"/>
-                        <constraint firstItem="39T-t6-0Wv" firstAttribute="top" secondItem="0Jt-Nx-mxp" secondAttribute="top" constant="12" id="n3K-8r-3La"/>
-                        <constraint firstItem="9DQ-zy-Jq5" firstAttribute="centerY" secondItem="1Mw-7R-dLz" secondAttribute="centerY" id="nLM-s2-wmR"/>
-                        <constraint firstAttribute="trailing" secondItem="x52-Ag-qNB" secondAttribute="trailing" constant="18" id="ni0-Br-dtN"/>
-                        <constraint firstItem="x52-Ag-qNB" firstAttribute="width" secondItem="7U7-1u-Czi" secondAttribute="width" id="oIR-2W-yI8"/>
-                        <constraint firstItem="JzE-X8-lLe" firstAttribute="leading" secondItem="9DQ-zy-Jq5" secondAttribute="trailing" constant="8" id="rUr-IM-rz0"/>
-                        <constraint firstItem="1Mw-7R-dLz" firstAttribute="top" secondItem="7U7-1u-Czi" secondAttribute="bottom" constant="9" id="sf0-GH-t1q"/>
-                        <constraint firstItem="J1s-eN-oKW" firstAttribute="centerY" secondItem="7U7-1u-Czi" secondAttribute="centerY" id="vEG-9g-xuH"/>
-                        <constraint firstItem="9DQ-zy-Jq5" firstAttribute="width" secondItem="1Mw-7R-dLz" secondAttribute="width" id="wD2-ML-f5L"/>
-                    </constraints>
-                    <userDefinedRuntimeAttributes>
-                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                            <real key="value" value="10"/>
-                        </userDefinedRuntimeAttribute>
-                    </userDefinedRuntimeAttributes>
-                </view>
-                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ih1-GM-HgL">
-                    <rect key="frame" x="741" y="75.5" width="44" height="44"/>
-                    <constraints>
-                        <constraint firstAttribute="height" constant="44" id="9oe-3I-cob"/>
-                        <constraint firstAttribute="width" constant="44" id="QQk-YE-bdJ"/>
-                    </constraints>
-                    <state key="normal" image="cloud_cancle"/>
-                </button>
-            </subviews>
-            <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.52000000000000002" colorSpace="custom" customColorSpace="sRGB"/>
-            <constraints>
-                <constraint firstItem="0Jt-Nx-mxp" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="9xt-7i-vZa"/>
-                <constraint firstItem="ih1-GM-HgL" firstAttribute="centerY" secondItem="0Jt-Nx-mxp" secondAttribute="top" id="ORp-y4-6jt"/>
-                <constraint firstItem="ih1-GM-HgL" firstAttribute="leading" secondItem="0Jt-Nx-mxp" secondAttribute="trailing" id="Yqg-ks-j0d"/>
-                <constraint firstItem="0Jt-Nx-mxp" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="vRQ-QD-vwY"/>
-            </constraints>
-            <nil key="simulatedTopBarMetrics"/>
-            <nil key="simulatedBottomBarMetrics"/>
-            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
-            <connections>
-                <outlet property="countLabel" destination="9Jw-La-2Hn" id="Pbq-Rz-Khb"/>
-                <outlet property="textView" destination="l1z-4Y-3eT" id="xeT-Xf-3MD"/>
-                <outlet property="tipsLabel" destination="nvM-32-Z6W" id="pKp-zJ-BqV"/>
-            </connections>
-            <point key="canvasLocation" x="-4.3478260869565224" y="-53.90625"/>
-        </view>
-    </objects>
-    <resources>
-        <image name="cloud_cancle" width="26" height="26"/>
-        <systemColor name="labelColor">
-            <color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-        </systemColor>
-        <systemColor name="systemBackgroundColor">
-            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-        </systemColor>
-    </resources>
-</document>

+ 0 - 23
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Help/CloudHelpView.h

@@ -1,23 +0,0 @@
-//
-//  CloudHelpView.h
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/15.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-typedef void(^CloudFeedbackAction)(void);
-
-@interface CloudHelpView : UIView
-
-+ (instancetype)shareInstance;
-
-- (void)feedbackCallback:(CloudFeedbackAction)callback;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 253
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Help/CloudHelpView.m

@@ -1,253 +0,0 @@
-//
-//  CloudHelpView.m
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/15.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import "CloudHelpView.h"
-#import <WebKit/WebKit.h>
-#import <KSToolLibrary/WeakWebViewScriptMessageDelegate.h>
-@interface CloudHelpView ()
-
-@property (weak, nonatomic) IBOutlet UIButton *guideButton;
-@property (weak, nonatomic) IBOutlet UIView *backView;
-
-@property (weak, nonatomic) IBOutlet UIButton *helpButton;
-@property (weak, nonatomic) IBOutlet UIView *lineView;
-@property (weak, nonatomic) IBOutlet UIView *baseView;
-@property (weak, nonatomic) IBOutlet NSLayoutConstraint *lineViewLeft;
-
-@property (nonatomic, strong) UIScrollView *baseScrollView;
-
-@property (nonatomic, strong) WKWebView *guideWebView;
-
-@property (nonatomic, strong) WKWebView *helpWebView;
-
-@property (nonatomic, strong) UIButton *feedbackButton;
-
-@property (nonatomic, strong) CloudFeedbackAction callback;
-
-@end
-
-@implementation CloudHelpView
-
-+ (instancetype)shareInstance {
-    CloudHelpView *view = [[[NSBundle mainBundle] loadNibNamed:@"CloudHelpView" owner:nil options:nil] firstObject];
-    [view configHelpView];
-    return view;
-}
-
-- (void)configHelpView {
-    
-    if (@available(iOS 11.0, *)) {
-        self.backView.layer.cornerRadius = 14;
-        self.backView.layer.maskedCorners = kCALayerMinXMinYCorner | kCALayerMinXMaxYCorner; // 左上圆角
-    }
-    else {
-        UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:self.backView.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerBottomLeft cornerRadii:CGSizeMake(14, 14)];
-        CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
-        maskLayer.frame = self.backView.bounds;
-        maskLayer.path = path.CGPath;
-        self.backView.layer.mask = maskLayer;
-    }
-
-    [self.baseView addSubview:self.baseScrollView];
-    [self.baseScrollView addSubview:self.guideWebView];
-    [self.baseScrollView addSubview:self.helpWebView];
-    [self setUserAgent];
-    [self.baseScrollView addSubview:self.feedbackButton];
-}
-
-
-
-- (void)setUserAgent {
-    
-    MJWeakSelf;
-    [self.guideWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) {
-        NSString *oldUserAgent = result;
-        NSString *newUserAgent = [NSString stringWithFormat:@"%@ %@",oldUserAgent,@"DAYAAPPI"];
-        weakSelf.guideWebView.customUserAgent = newUserAgent;
-        [weakSelf loadRequestIsGuide:YES];
-    }];
-    [self.helpWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) {
-        NSString *oldUserAgent = result;
-        NSString *newUserAgent = [NSString stringWithFormat:@"%@ %@",oldUserAgent,@"DAYAAPPI"];
-        weakSelf.helpWebView.customUserAgent = newUserAgent;
-        [weakSelf loadRequestIsGuide:NO];;
-    }];
-}
-
-- (void)loadRequestIsGuide:(BOOL)isGuide {
-    MJWeakSelf;
-    if (isGuide) {
-        [self.guideWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
-            NSLog(@"%@",result);
-            NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[weakSelf getUrlIsGuide:YES]] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0f];
-            [weakSelf.guideWebView loadRequest:request];
-        }];
-    }
-    else {
-        [self.helpWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
-            NSLog(@"%@",result);
-            NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[weakSelf getUrlIsGuide:NO]] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0f];
-            [weakSelf.helpWebView loadRequest:request];
-        }];
-    }
-}
-
-- (NSString *)getUrlIsGuide:(BOOL)isGuide {
-    NSString *tokenStr = UserDefault(TokenKey);
-    NSString *token = nil;
-    if (![NSString isEmptyString:tokenStr]) {
-        token = [[NSString stringWithFormat:@"Authorization=%@ %@", UserDefault(Token_type), tokenStr] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
-    }
-    if (isGuide) {
-        NSString *url = @"https://mteaonline.dayaedu.com/#/guide";
-        if (![NSString isEmptyString:token]) {
-            url = [NSString stringWithFormat:@"%@?%@",url,token];
-        }
-        return url;
-    }
-    else {
-        NSString *url = @"https://mstuonline.dayaedu.com/#/KeepRepaire?mode=accompany";
-        if (![NSString isEmptyString:token]) {
-            url = [NSString stringWithFormat:@"%@&%@",url,token];
-        }
-        return url;
-    }
-}
-
-
-- (void)feedbackCallback:(CloudFeedbackAction)callback {
-    if (callback) {
-        self.callback = callback;
-    }
-}
-
-- (IBAction)guideAction:(id)sender { // 投屏
-    [self configGuideChoose:YES];
-}
-
-- (IBAction)helpAction:(id)sender { // 帮助
-    [self configGuideChoose:NO];
-}
-
-- (void)configGuideChoose:(BOOL)isChooseSettingButton {
-    CGFloat positionX = 0.0f;
-    NSInteger pageIndex = 0;
-    if (isChooseSettingButton) {
-        [self.guideButton setTitleColor:THEMECOLOR forState:UIControlStateNormal];
-        [self.helpButton setTitleColor:HexRGB(0x1a1a1a) forState:UIControlStateNormal];
-        positionX = 65.0f;
-        pageIndex = 0;
-    }
-    else {
-        [self.guideButton setTitleColor:HexRGB(0x1a1a1a) forState:UIControlStateNormal];
-        [self.helpButton setTitleColor:THEMECOLOR forState:UIControlStateNormal];
-        positionX = 225.0f;
-        pageIndex = 1;
-    }
-    [UIView animateWithDuration:0.5f animations:^{
-        self.lineViewLeft.constant = positionX;
-        [self.baseScrollView setContentOffset:CGPointMake(pageIndex*320, 0)];
-    }];
-}
-
-- (IBAction)hideButtonAction:(id)sender {
-    [self removeFromSuperview];
-}
-
-- (void)feedbackButtonAction {
-    if (self.callback) {
-        self.callback();
-    }
-}
-
-#pragma mark ---- lazying
-- (UIScrollView *)baseScrollView {
-    if (!_baseScrollView) {
-        CGFloat height = KLandscapeHeight - 55;
-        _baseScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, height)];
-        [_baseScrollView setContentSize:CGSizeMake(CGRectGetHeight(self.baseView.frame)*2, height)];
-        _baseScrollView.scrollEnabled = NO;
-    }
-    return _baseScrollView;
-}
-
-- (WKWebView *)guideWebView {
-    if (!_guideWebView) {
-        _guideWebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, KLandscapeHeight) configuration:[self getwebConfig]];
-        _guideWebView.scrollView.bounces = NO;
-    }
-    return _guideWebView;
-}
-
-- (WKWebView *)helpWebView {
-    if (!_helpWebView) {
-        _helpWebView = [[WKWebView alloc] initWithFrame:CGRectMake(320, 0, 320, KLandscapeHeight - 55) configuration:[self getwebConfig]];
-        _helpWebView.scrollView.bounces = NO;
-    }
-    return _helpWebView;
-}
-
-- (WKWebViewConfiguration *)getwebConfig {
-    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
-    config.selectionGranularity = WKSelectionGranularityDynamic;
-    config.allowsInlineMediaPlayback = YES;
-    if (@available(iOS 10.0, *)) {
-        config.mediaTypesRequiringUserActionForPlayback = NO;
-    } else {
-        // Fallback on earlier versions
-        config.requiresUserActionForMediaPlayback = NO;
-    }
-    config.processPool = [CloudHelpView singleWkProcessPool];
-    config.websiteDataStore = [WKWebsiteDataStore defaultDataStore];
-    //自定义的WKScriptMessageHandler 是为了解决内存不释放的问题
-    WeakWebViewScriptMessageDelegate *weakScriptMessageDelegate = [[WeakWebViewScriptMessageDelegate alloc] initWithDelegate:self];
-    //这个类主要用来做native与JavaScript的交互管理
-    WKUserContentController * wkUController = [[WKUserContentController alloc] init];
-    [wkUController addScriptMessageHandler:weakScriptMessageDelegate name:@"DAYA"];
-    config.userContentController = wkUController;
-    
-    WKPreferences *preferences = [WKPreferences new];
-    // 是否支出javaScript
-    preferences.javaScriptEnabled = YES;
-    //不通过用户交互,是否可以打开窗口
-    preferences.javaScriptCanOpenWindowsAutomatically = YES;
-    config.preferences = preferences;
-    return config;
-}
-
-- (UIButton *)feedbackButton {
-    if (!_feedbackButton) {
-        _feedbackButton = [UIButton buttonWithType:UIButtonTypeCustom];
-        _feedbackButton.frame = CGRectMake(320, KLandscapeHeight - 55 - 55, 320, 55);
-        [_feedbackButton setTitle:@"意见反馈 >" forState:UIControlStateNormal];
-        [_feedbackButton setTitleColor:THEMECOLOR forState:UIControlStateNormal];
-        [_feedbackButton.titleLabel setFont:[UIFont systemFontOfSize:14.0f]];
-        [_feedbackButton addTarget:self action:@selector(feedbackButtonAction) forControlEvents:UIControlEventTouchUpInside];
-    }
-    return _feedbackButton;
-}
-
-
-+ (WKProcessPool*)singleWkProcessPool {
-    static WKProcessPool *sharedPool;
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-        sharedPool = [[WKProcessPool alloc] init];
-    });
-    return sharedPool;
-}
-
-/*
-// Only override drawRect: if you perform custom drawing.
-// An empty implementation adversely affects performance during animation.
-- (void)drawRect:(CGRect)rect {
-    // Drawing code
-}
-*/
-
-@end

+ 0 - 131
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/Help/CloudHelpView.xib

@@ -1,131 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
-    <device id="retina6_1" orientation="portrait" appearance="light"/>
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
-        <capability name="System colors in document resources" minToolsVersion="11.0"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <objects>
-        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
-        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="CloudHelpView">
-            <rect key="frame" x="0.0" y="0.0" width="664" height="386"/>
-            <autoresizingMask key="autoresizingMask"/>
-            <subviews>
-                <view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="obm-zW-QzQ">
-                    <rect key="frame" x="344" y="0.0" width="320" height="386"/>
-                    <subviews>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Pfo-si-2Hf">
-                            <rect key="frame" x="50" y="0.0" width="60" height="55"/>
-                            <constraints>
-                                <constraint firstAttribute="width" constant="60" id="uvn-eh-hGh"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
-                            <state key="normal" title="投屏">
-                                <color key="titleColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            </state>
-                            <connections>
-                                <action selector="guideAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="z9N-4C-3t8"/>
-                            </connections>
-                        </button>
-                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="WNO-Ji-qbp">
-                            <rect key="frame" x="65" y="51" width="30" height="3"/>
-                            <color key="backgroundColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <constraints>
-                                <constraint firstAttribute="width" constant="30" id="JJC-YP-gAm"/>
-                                <constraint firstAttribute="height" constant="3" id="S3K-Kl-hfz"/>
-                            </constraints>
-                            <userDefinedRuntimeAttributes>
-                                <userDefinedRuntimeAttribute type="number" keyPath="layer.CornerRadius">
-                                    <real key="value" value="1.5"/>
-                                </userDefinedRuntimeAttribute>
-                            </userDefinedRuntimeAttributes>
-                        </view>
-                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uc4-t2-7YM">
-                            <rect key="frame" x="0.0" y="55" width="320" height="1"/>
-                            <color key="backgroundColor" red="0.94117647059999998" green="0.94117647059999998" blue="0.94117647059999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="1" id="k4O-rI-Awa"/>
-                            </constraints>
-                        </view>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="lBO-uK-4OU">
-                            <rect key="frame" x="210" y="0.0" width="60" height="55"/>
-                            <constraints>
-                                <constraint firstAttribute="width" constant="60" id="vu6-VN-5eC"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
-                            <state key="normal" title="帮助">
-                                <color key="titleColor" red="0.1019607843" green="0.1019607843" blue="0.1019607843" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            </state>
-                            <connections>
-                                <action selector="helpAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="1JP-jM-sMu"/>
-                            </connections>
-                        </button>
-                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="71I-Qi-kjr">
-                            <rect key="frame" x="0.0" y="56" width="320" height="330"/>
-                            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                        </view>
-                    </subviews>
-                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                    <constraints>
-                        <constraint firstAttribute="trailing" secondItem="uc4-t2-7YM" secondAttribute="trailing" id="0dz-Ph-iv1"/>
-                        <constraint firstItem="Pfo-si-2Hf" firstAttribute="top" secondItem="obm-zW-QzQ" secondAttribute="top" id="0so-tT-vKx"/>
-                        <constraint firstItem="uc4-t2-7YM" firstAttribute="leading" secondItem="obm-zW-QzQ" secondAttribute="leading" id="4V8-I7-BUQ"/>
-                        <constraint firstItem="uc4-t2-7YM" firstAttribute="top" secondItem="lBO-uK-4OU" secondAttribute="bottom" id="9GF-0F-mT8"/>
-                        <constraint firstItem="WNO-Ji-qbp" firstAttribute="leading" secondItem="obm-zW-QzQ" secondAttribute="leading" constant="65" id="Cel-5r-oZ9"/>
-                        <constraint firstItem="uc4-t2-7YM" firstAttribute="top" secondItem="WNO-Ji-qbp" secondAttribute="bottom" constant="1" id="Z93-Es-h8v"/>
-                        <constraint firstItem="71I-Qi-kjr" firstAttribute="top" secondItem="uc4-t2-7YM" secondAttribute="bottom" id="a6k-qz-AQp"/>
-                        <constraint firstAttribute="width" constant="320" id="gnO-9b-8yi"/>
-                        <constraint firstItem="lBO-uK-4OU" firstAttribute="centerX" secondItem="obm-zW-QzQ" secondAttribute="centerX" multiplier="1.5" id="ium-a0-a9D"/>
-                        <constraint firstItem="uc4-t2-7YM" firstAttribute="top" secondItem="Pfo-si-2Hf" secondAttribute="bottom" id="ixj-NX-tsw"/>
-                        <constraint firstAttribute="bottom" secondItem="71I-Qi-kjr" secondAttribute="bottom" id="j6y-lQ-MyW"/>
-                        <constraint firstItem="lBO-uK-4OU" firstAttribute="top" secondItem="obm-zW-QzQ" secondAttribute="top" id="odh-RK-gZ6"/>
-                        <constraint firstItem="Pfo-si-2Hf" firstAttribute="centerX" secondItem="obm-zW-QzQ" secondAttribute="centerX" multiplier="0.5" id="ps6-fp-tnP"/>
-                        <constraint firstItem="uc4-t2-7YM" firstAttribute="top" secondItem="obm-zW-QzQ" secondAttribute="top" constant="55" id="q58-oF-BP6"/>
-                        <constraint firstItem="71I-Qi-kjr" firstAttribute="leading" secondItem="obm-zW-QzQ" secondAttribute="leading" id="qjc-20-qyp"/>
-                        <constraint firstAttribute="trailing" secondItem="71I-Qi-kjr" secondAttribute="trailing" id="ruC-NP-2Gb"/>
-                    </constraints>
-                </view>
-                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9oz-N7-A8a">
-                    <rect key="frame" x="314" y="171" width="30" height="44"/>
-                    <constraints>
-                        <constraint firstAttribute="width" constant="30" id="EZT-YP-4uR"/>
-                        <constraint firstAttribute="height" constant="44" id="Pg5-h0-M6s"/>
-                    </constraints>
-                    <state key="normal" image="help_hide"/>
-                    <connections>
-                        <action selector="hideButtonAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="srH-JR-kyz"/>
-                    </connections>
-                </button>
-            </subviews>
-            <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.52000000000000002" colorSpace="custom" customColorSpace="sRGB"/>
-            <constraints>
-                <constraint firstItem="9oz-N7-A8a" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="9Y1-dp-fZY"/>
-                <constraint firstAttribute="bottom" secondItem="obm-zW-QzQ" secondAttribute="bottom" id="aNJ-Eu-aUX"/>
-                <constraint firstItem="obm-zW-QzQ" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="djf-ox-UZr"/>
-                <constraint firstItem="obm-zW-QzQ" firstAttribute="trailing" secondItem="iN0-l3-epB" secondAttribute="trailing" id="lR7-Xg-NWG"/>
-                <constraint firstItem="obm-zW-QzQ" firstAttribute="leading" secondItem="9oz-N7-A8a" secondAttribute="trailing" id="rqU-Um-xDZ"/>
-            </constraints>
-            <nil key="simulatedTopBarMetrics"/>
-            <nil key="simulatedBottomBarMetrics"/>
-            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
-            <connections>
-                <outlet property="backView" destination="obm-zW-QzQ" id="Xt4-WW-JX9"/>
-                <outlet property="baseView" destination="71I-Qi-kjr" id="CuG-VD-HGS"/>
-                <outlet property="guideButton" destination="Pfo-si-2Hf" id="yEj-8V-jim"/>
-                <outlet property="helpButton" destination="lBO-uK-4OU" id="dQs-Y4-hN3"/>
-                <outlet property="lineView" destination="WNO-Ji-qbp" id="WQ2-d8-T5g"/>
-                <outlet property="lineViewLeft" destination="Cel-5r-oZ9" id="5jX-dg-uBc"/>
-            </connections>
-            <point key="canvasLocation" x="257.97101449275362" y="-97.098214285714278"/>
-        </view>
-    </objects>
-    <resources>
-        <image name="help_hide" width="30" height="44"/>
-        <systemColor name="systemBackgroundColor">
-            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-        </systemColor>
-    </resources>
-</document>

+ 0 - 29
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/JudgePageView.h

@@ -1,29 +0,0 @@
-//
-//  JudgePageView.h
-//  MidiPlayer
-//
-//  Created by Kyle on 2021/12/7.
-//
-
-#import <UIKit/UIKit.h>
-#import "KSCloudSettingView.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface JudgePageView : UIView
-
-@property (nonatomic, assign) NSString *level; //评测难度
-
-@property (nonatomic, assign) BOOL saveVideo;   // 是否保存到相册
-
-@property (nonatomic, assign) BOOL accompanyOn; // 是否开启伴奏
-
-+ (instancetype)shareInstance;
-
-- (void)querySettingConfig;
-
-- (void)judgeSettingCallback:(CloudSettingCallback)callback;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 176
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/JudgePageView.m

@@ -1,176 +0,0 @@
-//
-//  JudgePageView.m
-//  MidiPlayer
-//
-//  Created by Kyle on 2021/12/7.
-//
-
-#import "JudgePageView.h"
-
-@interface JudgePageView ()
-
-@property (weak, nonatomic) IBOutlet UIButton *primerButton;
-
-@property (weak, nonatomic) IBOutlet UIButton *advancedButton;
-
-@property (weak, nonatomic) IBOutlet UIButton *masterButton;
-
-@property (weak, nonatomic) IBOutlet UIButton *saveButton;
-
-@property (weak, nonatomic) IBOutlet UIButton *accompanyButton;
-
-@property (nonatomic, copy) CloudSettingCallback callback;
-
-@property (nonatomic, strong) NSMutableDictionary *configDict;
-
-@end
-
-@implementation JudgePageView
-
-+ (instancetype)shareInstance {
-    JudgePageView *view = [[[NSBundle mainBundle] loadNibNamed:@"JudgePageView" owner:nil options:nil] firstObject];
-    [view querySettingConfig];
-    return view;
-}
-
-- (void)setButtonSelected:(BOOL)isSelected withButton:(UIButton *)button {
-    if (isSelected) {
-        button.backgroundColor = HexRGB(0xe2fff9);
-        button.layer.borderColor = THEMECOLOR.CGColor;
-        [button setTitleColor:THEMECOLOR forState:UIControlStateNormal];
-        [button.titleLabel setFont:[UIFont systemFontOfSize:14.0f weight:UIFontWeightMedium]];
-    }
-    else {
-        button.backgroundColor = HexRGB(0xf8f8f8);
-        button.layer.borderColor = HexRGB(0xf8f8f8).CGColor;
-        [button setTitleColor:HexRGB(0x666666) forState:UIControlStateNormal];
-        [button.titleLabel setFont:[UIFont systemFontOfSize:14.0f weight:UIFontWeightRegular]];
-    }
-}
-
-- (void)defaultSetting {
-    self.primerButton.layer.cornerRadius = 5.0f;
-    self.primerButton.layer.borderWidth = 1.0f;
-    
-    self.advancedButton.layer.cornerRadius = 5.0f;
-    self.advancedButton.layer.borderWidth = 1.0f;
-    
-    self.masterButton.layer.cornerRadius = 5.0f;
-    self.masterButton.layer.borderWidth = 1.0f;
-    
-    [self setButtonSelected:YES withButton:self.primerButton];
-    [self setButtonSelected:NO withButton:self.advancedButton];
-    [self setButtonSelected:NO withButton:self.masterButton];
-    self.level = @"BEGINNER";
-    self.accompanyOn = NO;
-    self.saveVideo = NO;
-}
-
-- (void)querySettingConfig {
-    [self defaultSetting];
-    
-    // 根据储存的配置项显示
-    NSDictionary *config = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"cloudConfig"];
-    
-    self.configDict = [NSMutableDictionary dictionaryWithDictionary:config];
-    self.level = [config ks_stringValueForKey:@"level"];
-    self.accompanyOn = [config ks_boolValueForKey:@"accompanyOn"];
-    self.saveVideo = [config ks_boolValueForKey:@"save"];
-    if ([self.level isEqualToString:@"BEGINNER"]) {
-        
-    }
-    else if ([self.level isEqualToString:@"ADVANCED"]) {
-        [self setButtonSelected:NO withButton:self.primerButton];
-        [self setButtonSelected:YES withButton:self.advancedButton];
-    }
-    else if ([self.level isEqualToString:@"PERFORMER"]) {
-        [self setButtonSelected:NO withButton:self.primerButton];
-        [self setButtonSelected:YES withButton:self.masterButton];
-    }
-    
-}
-
-- (void)synchronizeConfig {
-    [[NSUserDefaults standardUserDefaults] setObject:self.configDict forKey:@"cloudConfig"];
-    [[NSUserDefaults standardUserDefaults] synchronize];
-}
-
-- (void)judgeSettingCallback:(CloudSettingCallback)callback {
-    if (callback) {
-        self.callback = callback;
-    }
-}
-
-- (IBAction)levelButtonAction:(UIButton *)sender {
-    
-    NSInteger buttonIndex = sender.tag;
-    if (buttonIndex == 1001) {
-        self.level = @"BEGINNER";
-        [self setButtonSelected:YES withButton:self.primerButton];
-        [self setButtonSelected:NO withButton:self.advancedButton];
-        [self setButtonSelected:NO withButton:self.masterButton];
-        
-        [self.configDict setValue:@"BEGINNER" forKey:@"level"];
-    }
-    else if (buttonIndex == 1002) {
-        self.level = @"ADVANCED";
-        [self setButtonSelected:NO withButton:self.primerButton];
-        [self setButtonSelected:YES withButton:self.advancedButton];
-        [self setButtonSelected:NO withButton:self.masterButton];
-        [self.configDict setValue:@"ADVANCED" forKey:@"level"];
-    }
-    else {
-        self.level = @"PERFORMER";
-        [self setButtonSelected:NO withButton:self.primerButton];
-        [self setButtonSelected:NO withButton:self.advancedButton];
-        [self setButtonSelected:YES withButton:self.masterButton];
-        [self.configDict setValue:@"PERFORMER" forKey:@"level"];
-    }
-    [self synchronizeConfig];
-    
-    if (self.callback) {
-        self.callback(CLOUDSETTING_TYPE_LEVEL, NO, self.level);
-    }
-}
-
-- (IBAction)saveVideoAction:(UIButton *)sender {
-    self.saveVideo = !self.saveVideo;
-    [self.configDict setValue:@(self.saveVideo) forKey:@"save"];
-    [self synchronizeConfig];
-    if (self.callback) {
-        self.callback(CLOUDSETTING_TYPE_SAVEVIDEO, self.saveVideo, @"");
-    }
-}
-
-- (IBAction)accompanyAction:(id)sender {
-    self.accompanyOn = !self.accompanyOn;
-    [self.configDict setValue:@(self.accompanyOn) forKey:@"accompanyOn"];
-    [self synchronizeConfig];
-    if (self.callback) {
-        self.callback(CLOUDSETTING_TYPE_ACCOMPANY, self.accompanyOn, @"");
-    }
-    
-}
-
-#pragma mark -- setter
-- (void)setAccompanyOn:(BOOL)accompanyOn {
-    _accompanyOn = accompanyOn;
-    NSString *imageName = accompanyOn ? @"switch_on" : @"switch_off";
-    [self.accompanyButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
-}
-
-- (void)setSaveVideo:(BOOL)saveVideo {
-    _saveVideo = saveVideo;
-    NSString *imageName = saveVideo ? @"switch_on" : @"switch_off";
-    [self.saveButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
-}
-
-/*
-// Only override drawRect: if you perform custom drawing.
-// An empty implementation adversely affects performance during animation.
-- (void)drawRect:(CGRect)rect {
-    // Drawing code
-}
-*/
-
-@end

+ 0 - 157
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/JudgePageView.xib

@@ -1,157 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
-    <device id="retina6_1" orientation="portrait" appearance="light"/>
-    <dependencies>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
-        <capability name="System colors in document resources" minToolsVersion="11.0"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <objects>
-        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
-        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="JudgePageView">
-            <rect key="frame" x="0.0" y="0.0" width="414" height="357"/>
-            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-            <subviews>
-                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="请选择评测难度" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="6tM-MJ-pJi">
-                    <rect key="frame" x="18" y="14" width="100" height="20"/>
-                    <constraints>
-                        <constraint firstAttribute="height" constant="20" id="UhA-MQ-PwR"/>
-                    </constraints>
-                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                    <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                    <nil key="highlightedColor"/>
-                </label>
-                <button opaque="NO" tag="1001" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Mix-L6-JTm">
-                    <rect key="frame" x="18" y="44" width="122.5" height="30"/>
-                    <color key="backgroundColor" red="0.88627450980392153" green="1" blue="0.97647058823529409" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                    <constraints>
-                        <constraint firstAttribute="height" constant="30" id="9PN-D0-3W4"/>
-                    </constraints>
-                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                    <state key="normal" title="入门级">
-                        <color key="titleColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                    </state>
-                    <connections>
-                        <action selector="levelButtonAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="UAc-wl-i3a"/>
-                    </connections>
-                </button>
-                <button opaque="NO" tag="1002" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1Ba-L1-uR3">
-                    <rect key="frame" x="145.5" y="44" width="123" height="30"/>
-                    <color key="backgroundColor" red="0.97254901960784312" green="0.97254901960784312" blue="0.97254901960784312" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                    <state key="normal" title="进阶级">
-                        <color key="titleColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                    </state>
-                    <connections>
-                        <action selector="levelButtonAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="R5s-ej-zFk"/>
-                    </connections>
-                </button>
-                <button opaque="NO" tag="1003" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yaq-mM-z7i">
-                    <rect key="frame" x="273.5" y="44" width="122.5" height="30"/>
-                    <color key="backgroundColor" red="0.97254901960784312" green="0.97254901960784312" blue="0.97254901960784312" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                    <state key="normal" title="大师级">
-                        <color key="titleColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                    </state>
-                    <connections>
-                        <action selector="levelButtonAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="HIW-wJ-OsT"/>
-                    </connections>
-                </button>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ewd-ee-kt8">
-                    <rect key="frame" x="0.0" y="94" width="414" height="50"/>
-                    <subviews>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="保存到相册" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mBe-Xi-HzQ">
-                            <rect key="frame" x="25" y="16" width="76.5" height="18"/>
-                            <fontDescription key="fontDescription" type="system" pointSize="15"/>
-                            <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="v9d-6q-6e7">
-                            <rect key="frame" x="342" y="0.0" width="47" height="50"/>
-                            <state key="normal" image="switch_off"/>
-                            <connections>
-                                <action selector="saveVideoAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="pM0-BB-58b"/>
-                            </connections>
-                        </button>
-                    </subviews>
-                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                    <constraints>
-                        <constraint firstItem="v9d-6q-6e7" firstAttribute="top" secondItem="ewd-ee-kt8" secondAttribute="top" id="7yN-C5-3LK"/>
-                        <constraint firstAttribute="height" constant="50" id="ABJ-aC-X3d"/>
-                        <constraint firstAttribute="trailing" secondItem="v9d-6q-6e7" secondAttribute="trailing" constant="25" id="Lg4-nm-UEh"/>
-                        <constraint firstItem="mBe-Xi-HzQ" firstAttribute="leading" secondItem="ewd-ee-kt8" secondAttribute="leading" constant="25" id="q3b-dc-YC5"/>
-                        <constraint firstItem="mBe-Xi-HzQ" firstAttribute="centerY" secondItem="ewd-ee-kt8" secondAttribute="centerY" id="xiw-AK-3l4"/>
-                        <constraint firstAttribute="bottom" secondItem="v9d-6q-6e7" secondAttribute="bottom" id="yCX-Tw-oXC"/>
-                    </constraints>
-                </view>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wT6-4G-RF6">
-                    <rect key="frame" x="0.0" y="144" width="414" height="50"/>
-                    <subviews>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="开启伴奏" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EGX-eA-JmP">
-                            <rect key="frame" x="25" y="16" width="61.5" height="18"/>
-                            <fontDescription key="fontDescription" type="system" pointSize="15"/>
-                            <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="TiY-1T-4xp">
-                            <rect key="frame" x="342" y="0.0" width="47" height="50"/>
-                            <state key="normal" image="switch_off"/>
-                            <connections>
-                                <action selector="accompanyAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="oDS-hQ-fsL"/>
-                            </connections>
-                        </button>
-                    </subviews>
-                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                    <constraints>
-                        <constraint firstAttribute="height" constant="50" id="HxP-dR-8c0"/>
-                        <constraint firstItem="EGX-eA-JmP" firstAttribute="centerY" secondItem="wT6-4G-RF6" secondAttribute="centerY" id="NEJ-PG-EAZ"/>
-                        <constraint firstItem="TiY-1T-4xp" firstAttribute="top" secondItem="wT6-4G-RF6" secondAttribute="top" id="Vuy-vz-yRz"/>
-                        <constraint firstItem="EGX-eA-JmP" firstAttribute="leading" secondItem="wT6-4G-RF6" secondAttribute="leading" constant="25" id="WqS-4b-dJf"/>
-                        <constraint firstAttribute="bottom" secondItem="TiY-1T-4xp" secondAttribute="bottom" id="nHp-fe-9n3"/>
-                        <constraint firstAttribute="trailing" secondItem="TiY-1T-4xp" secondAttribute="trailing" constant="25" id="vUS-JS-DBi"/>
-                    </constraints>
-                </view>
-            </subviews>
-            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-            <constraints>
-                <constraint firstItem="yaq-mM-z7i" firstAttribute="width" secondItem="Mix-L6-JTm" secondAttribute="width" id="6bo-sh-Nwi"/>
-                <constraint firstItem="wT6-4G-RF6" firstAttribute="trailing" secondItem="ewd-ee-kt8" secondAttribute="trailing" id="7o6-A3-2si"/>
-                <constraint firstItem="1Ba-L1-uR3" firstAttribute="height" secondItem="Mix-L6-JTm" secondAttribute="height" id="DLz-1P-vYA"/>
-                <constraint firstItem="6tM-MJ-pJi" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="14" id="GNi-xR-SgQ"/>
-                <constraint firstItem="6tM-MJ-pJi" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="18" id="JmM-tg-2JP"/>
-                <constraint firstItem="ewd-ee-kt8" firstAttribute="top" secondItem="Mix-L6-JTm" secondAttribute="bottom" constant="20" id="Ky4-rH-ieE"/>
-                <constraint firstItem="Mix-L6-JTm" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="18" id="N1w-be-fcb"/>
-                <constraint firstAttribute="trailing" secondItem="yaq-mM-z7i" secondAttribute="trailing" constant="18" id="Qni-vs-IQ5"/>
-                <constraint firstItem="yaq-mM-z7i" firstAttribute="centerY" secondItem="Mix-L6-JTm" secondAttribute="centerY" id="RHc-4i-LCz"/>
-                <constraint firstItem="ewd-ee-kt8" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="T2Z-Rf-LUn"/>
-                <constraint firstItem="1Ba-L1-uR3" firstAttribute="width" secondItem="Mix-L6-JTm" secondAttribute="width" id="VOu-dl-xiJ"/>
-                <constraint firstItem="Mix-L6-JTm" firstAttribute="top" secondItem="6tM-MJ-pJi" secondAttribute="bottom" constant="10" id="Xei-zn-Itl"/>
-                <constraint firstItem="yaq-mM-z7i" firstAttribute="leading" secondItem="1Ba-L1-uR3" secondAttribute="trailing" constant="5" id="YYC-2y-ScH"/>
-                <constraint firstItem="wT6-4G-RF6" firstAttribute="leading" secondItem="ewd-ee-kt8" secondAttribute="leading" id="cAn-uv-UNL"/>
-                <constraint firstAttribute="trailing" secondItem="ewd-ee-kt8" secondAttribute="trailing" id="fYt-iT-CUo"/>
-                <constraint firstItem="1Ba-L1-uR3" firstAttribute="centerY" secondItem="Mix-L6-JTm" secondAttribute="centerY" id="hx4-zc-P3c"/>
-                <constraint firstItem="1Ba-L1-uR3" firstAttribute="leading" secondItem="Mix-L6-JTm" secondAttribute="trailing" constant="5" id="udr-3Q-VlX"/>
-                <constraint firstItem="wT6-4G-RF6" firstAttribute="top" secondItem="ewd-ee-kt8" secondAttribute="bottom" id="xWz-Qo-3Pw"/>
-                <constraint firstItem="yaq-mM-z7i" firstAttribute="height" secondItem="Mix-L6-JTm" secondAttribute="height" id="ynh-O9-NS9"/>
-            </constraints>
-            <nil key="simulatedTopBarMetrics"/>
-            <nil key="simulatedBottomBarMetrics"/>
-            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
-            <connections>
-                <outlet property="accompanyButton" destination="TiY-1T-4xp" id="UXU-9m-y1O"/>
-                <outlet property="advancedButton" destination="1Ba-L1-uR3" id="mli-9q-Z1z"/>
-                <outlet property="masterButton" destination="yaq-mM-z7i" id="boo-lD-3gf"/>
-                <outlet property="primerButton" destination="Mix-L6-JTm" id="aCK-L5-fDs"/>
-                <outlet property="saveButton" destination="v9d-6q-6e7" id="mnk-y8-eQ9"/>
-            </connections>
-            <point key="canvasLocation" x="76.811594202898561" y="-12.388392857142856"/>
-        </view>
-    </objects>
-    <resources>
-        <image name="switch_off" width="47" height="24"/>
-        <systemColor name="systemBackgroundColor">
-            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-        </systemColor>
-    </resources>
-</document>

+ 0 - 36
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/KSCloudSettingView.h

@@ -1,36 +0,0 @@
-//
-//  KSCloudSettingView.h
-//  MidiPlayer
-//
-//  Created by Kyle on 2021/12/7.
-//
-
-#import <UIKit/UIKit.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-typedef NS_ENUM(NSInteger, CLOUDSETTING_TYPE) {
-    CLOUDSETTING_TYPE_EYESHIELD,    // 护眼模式
-    CLOUDSETTING_TYPE_SOUNDCHECK,   // 校音
-    CLOUDSETTING_TYPE_CAMERA,       // 摄像头
-    CLOUDSETTING_TYPE_REPEAT,       // 循环播放
-    CLOUDSETTING_TYPE_FINGER,       // 显示指法
-    CLOUDSETTING_TYPE_LEVEL,        // 评测级别
-    CLOUDSETTING_TYPE_SAVEVIDEO,    // 保存视频
-    CLOUDSETTING_TYPE_ACCOMPANY,    // 伴奏
-};
-
-
-typedef void(^CloudSettingCallback)(CLOUDSETTING_TYPE type, BOOL isOn, NSString *level);
-
-/// 云教练设置页面
-@interface KSCloudSettingView : UIView
-
-+ (instancetype)shareInstance;
-
-
-- (void)settingCallback:(CloudSettingCallback)callback;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 139
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/KSCloudSettingView.m

@@ -1,139 +0,0 @@
-//
-//  KSCloudSettingView.m
-//  MidiPlayer
-//
-//  Created by Kyle on 2021/12/7.
-//
-
-#import "KSCloudSettingView.h"
-#import "SettingPageView.h"
-#import "JudgePageView.h"
-
-@interface KSCloudSettingView ()
-
-@property (nonatomic, copy) CloudSettingCallback callback;
-
-@property (weak, nonatomic) IBOutlet UIButton *settingButton;
-
-@property (weak, nonatomic) IBOutlet UIButton *judgeButton;
-
-@property (weak, nonatomic) IBOutlet UIView *lineView;
-
-@property (weak, nonatomic) IBOutlet UIView *baseView;
-
-@property (weak, nonatomic) IBOutlet NSLayoutConstraint *lineViewLeft;
-
-@property (nonatomic, strong) UIScrollView *baseScrollView;
-
-@property (nonatomic, strong) SettingPageView *settingView;
-
-@property (nonatomic, strong) JudgePageView *judgeView;
-
-@end
-
-
-@implementation KSCloudSettingView
-
-+ (instancetype)shareInstance {
-    KSCloudSettingView *view = [[[NSBundle mainBundle] loadNibNamed:@"KSCloudSettingView" owner:nil options:nil] firstObject];
-    [view configSettingView];
-    return view;
-}
-
-- (void)settingCallback:(CloudSettingCallback)callback {
-    if (callback) {
-        self.callback = callback;
-    }
-}
-
-- (void)configSettingView {
-    
-    
-    [self.baseView addSubview:self.baseScrollView];
-    [self.baseScrollView addSubview:self.settingView];
-    [self.baseScrollView addSubview:self.judgeView];
-    
-}
-
-- (IBAction)settingAction:(id)sender { // 设置
-    [self configSettingChoose:YES];
-}
-
-- (IBAction)judgeAction:(id)sender { // 评测
-    [self configSettingChoose:NO];
-}
-
-- (IBAction)cancleAction:(id)sender {
-    [self removeFromSuperview];
-}
-
-- (void)configSettingChoose:(BOOL)isChooseSettingButton {
-    CGFloat positionX = 0.0f;
-    NSInteger pageIndex = 0;
-    if (isChooseSettingButton) {
-        [self.settingButton setTitleColor:THEMECOLOR forState:UIControlStateNormal];
-        [self.judgeButton setTitleColor:HexRGB(0x1a1a1a) forState:UIControlStateNormal];
-        positionX = 65.0f;
-        pageIndex = 0;
-    }
-    else {
-        [self.settingButton setTitleColor:HexRGB(0x1a1a1a) forState:UIControlStateNormal];
-        [self.judgeButton setTitleColor:THEMECOLOR forState:UIControlStateNormal];
-        positionX = 225.0f;
-        pageIndex = 1;
-    }
-    [UIView animateWithDuration:0.5f animations:^{
-        self.lineViewLeft.constant = positionX;
-        [self.baseScrollView setContentOffset:CGPointMake(pageIndex*320, 0)];
-    }];
-}
-
-#pragma mark ---- lazying
-- (UIScrollView *)baseScrollView {
-    if (!_baseScrollView) {
-        CGFloat height = CGRectGetHeight(self.frame) - 33*2 - 55;
-        _baseScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, height)];
-        [_baseScrollView setContentSize:CGSizeMake(320*2, height)];
-        _baseScrollView.scrollEnabled = NO;
-    }
-    return _baseScrollView;
-}
-
-- (SettingPageView *)settingView {
-    if (!_settingView) {
-        CGFloat height = CGRectGetHeight(self.frame) - 33*2 - 55;
-        _settingView = [SettingPageView shareInstance];
-        _settingView.frame = CGRectMake(0, 0, 320, height);
-        __weak typeof(self) weakSelf = self;
-        [_settingView settingCallback:^(CLOUDSETTING_TYPE type, BOOL isOn) {
-            if (weakSelf.callback) {
-                weakSelf.callback(type, isOn, @"");
-            }
-        }];
-    }
-    return _settingView;
-}
-
-- (JudgePageView *)judgeView {
-    if (!_judgeView) {
-        CGFloat height = CGRectGetHeight(self.frame) - 33*2 - 55;
-        _judgeView = [JudgePageView shareInstance];
-        _judgeView.frame = CGRectMake(320, 0, 320, height);
-        __weak typeof(self) weakSelf = self;
-        [_judgeView judgeSettingCallback:^(CLOUDSETTING_TYPE type, BOOL isOn, NSString * _Nonnull level) {
-            if (weakSelf.callback) {
-                weakSelf.callback(type, isOn, level);
-            }
-        }];
-    }
-    return _judgeView;
-}
-/*
-// Only override drawRect: if you perform custom drawing.
-// An empty implementation adversely affects performance during animation.
-- (void)drawRect:(CGRect)rect {
-    // Drawing code
-}
-*/
-
-@end

+ 0 - 135
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/KSCloudSettingView.xib

@@ -1,135 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
-    <device id="retina6_1" orientation="portrait" appearance="light"/>
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
-        <capability name="System colors in document resources" minToolsVersion="11.0"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <objects>
-        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
-        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="KSCloudSettingView">
-            <rect key="frame" x="0.0" y="0.0" width="765" height="340"/>
-            <autoresizingMask key="autoresizingMask"/>
-            <subviews>
-                <view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hfV-D9-4RA">
-                    <rect key="frame" x="222.5" y="33" width="320" height="274"/>
-                    <subviews>
-                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ZaF-YM-MHQ">
-                            <rect key="frame" x="0.0" y="54" width="320" height="1"/>
-                            <color key="backgroundColor" red="0.94117647058823528" green="0.94117647058823528" blue="0.94117647058823528" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="1" id="JMv-iI-n4b"/>
-                            </constraints>
-                        </view>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="p8P-5R-8Rj">
-                            <rect key="frame" x="50" y="0.0" width="60" height="54"/>
-                            <constraints>
-                                <constraint firstAttribute="width" constant="60" id="OK4-wC-P1G"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
-                            <state key="normal" title="设置">
-                                <color key="titleColor" red="0.0039215686274509803" green="0.75686274509803919" blue="0.70980392156862748" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            </state>
-                            <connections>
-                                <action selector="settingAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="ef8-rX-DbF"/>
-                            </connections>
-                        </button>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="a7T-m6-cO3">
-                            <rect key="frame" x="210" y="0.0" width="60" height="54"/>
-                            <constraints>
-                                <constraint firstAttribute="width" constant="60" id="HYZ-j2-02K"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
-                            <state key="normal" title="评测">
-                                <color key="titleColor" red="0.10196078431372549" green="0.10196078431372549" blue="0.10196078431372549" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            </state>
-                            <connections>
-                                <action selector="judgeAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="yT1-jF-wEg"/>
-                            </connections>
-                        </button>
-                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="C3c-hV-10p">
-                            <rect key="frame" x="65" y="50" width="30" height="3"/>
-                            <color key="backgroundColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <constraints>
-                                <constraint firstAttribute="width" constant="30" id="mPD-5O-93G"/>
-                                <constraint firstAttribute="height" constant="3" id="vgm-Wv-AR0"/>
-                            </constraints>
-                            <userDefinedRuntimeAttributes>
-                                <userDefinedRuntimeAttribute type="number" keyPath="layer.CornerRadius">
-                                    <real key="value" value="1.5"/>
-                                </userDefinedRuntimeAttribute>
-                            </userDefinedRuntimeAttributes>
-                        </view>
-                        <view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pPQ-tv-M04">
-                            <rect key="frame" x="0.0" y="55" width="320" height="219"/>
-                            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                        </view>
-                    </subviews>
-                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                    <constraints>
-                        <constraint firstAttribute="trailing" secondItem="ZaF-YM-MHQ" secondAttribute="trailing" id="0hN-uw-S9A"/>
-                        <constraint firstItem="ZaF-YM-MHQ" firstAttribute="top" secondItem="C3c-hV-10p" secondAttribute="bottom" constant="1" id="6n2-Bw-93p"/>
-                        <constraint firstItem="p8P-5R-8Rj" firstAttribute="centerX" secondItem="hfV-D9-4RA" secondAttribute="centerX" multiplier="0.5" id="AgX-v4-FXk"/>
-                        <constraint firstAttribute="bottom" secondItem="pPQ-tv-M04" secondAttribute="bottom" id="FdO-jV-SRW"/>
-                        <constraint firstItem="ZaF-YM-MHQ" firstAttribute="top" secondItem="a7T-m6-cO3" secondAttribute="bottom" id="LJK-pe-9BW"/>
-                        <constraint firstItem="pPQ-tv-M04" firstAttribute="leading" secondItem="hfV-D9-4RA" secondAttribute="leading" id="NMN-jt-5Dc"/>
-                        <constraint firstItem="ZaF-YM-MHQ" firstAttribute="top" secondItem="p8P-5R-8Rj" secondAttribute="bottom" id="OcI-9y-j24"/>
-                        <constraint firstItem="ZaF-YM-MHQ" firstAttribute="leading" secondItem="hfV-D9-4RA" secondAttribute="leading" id="RJY-gk-vSg"/>
-                        <constraint firstAttribute="trailing" secondItem="pPQ-tv-M04" secondAttribute="trailing" id="TVZ-d9-Jaw"/>
-                        <constraint firstItem="a7T-m6-cO3" firstAttribute="centerX" secondItem="hfV-D9-4RA" secondAttribute="centerX" multiplier="1.5" id="aBp-ee-0ie"/>
-                        <constraint firstAttribute="width" constant="320" id="apj-m7-hnD"/>
-                        <constraint firstItem="pPQ-tv-M04" firstAttribute="top" secondItem="ZaF-YM-MHQ" secondAttribute="bottom" id="npH-Ce-Fgh"/>
-                        <constraint firstItem="ZaF-YM-MHQ" firstAttribute="top" secondItem="hfV-D9-4RA" secondAttribute="top" constant="54" id="uxK-qx-D55"/>
-                        <constraint firstItem="C3c-hV-10p" firstAttribute="leading" secondItem="hfV-D9-4RA" secondAttribute="leading" constant="65" id="vrQ-K4-VVb"/>
-                        <constraint firstItem="p8P-5R-8Rj" firstAttribute="top" secondItem="hfV-D9-4RA" secondAttribute="top" id="yTP-om-2bY"/>
-                        <constraint firstItem="a7T-m6-cO3" firstAttribute="top" secondItem="hfV-D9-4RA" secondAttribute="top" id="zNK-WD-UU4"/>
-                    </constraints>
-                    <userDefinedRuntimeAttributes>
-                        <userDefinedRuntimeAttribute type="number" keyPath="layer.CornerRadius">
-                            <integer key="value" value="10"/>
-                        </userDefinedRuntimeAttribute>
-                    </userDefinedRuntimeAttributes>
-                </view>
-                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="q0f-Z3-hFt">
-                    <rect key="frame" x="542.5" y="11" width="44" height="44"/>
-                    <constraints>
-                        <constraint firstAttribute="height" constant="44" id="Gty-rQ-CAi"/>
-                        <constraint firstAttribute="width" constant="44" id="tQd-jw-Mrl"/>
-                    </constraints>
-                    <state key="normal" image="cloud_cancle"/>
-                    <connections>
-                        <action selector="cancleAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="MHR-ak-SfF"/>
-                    </connections>
-                </button>
-            </subviews>
-            <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.52000000000000002" colorSpace="custom" customColorSpace="sRGB"/>
-            <constraints>
-                <constraint firstItem="hfV-D9-4RA" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="33" id="5jd-PQ-73w"/>
-                <constraint firstItem="q0f-Z3-hFt" firstAttribute="leading" secondItem="hfV-D9-4RA" secondAttribute="trailing" id="6p1-95-Who"/>
-                <constraint firstItem="q0f-Z3-hFt" firstAttribute="centerY" secondItem="hfV-D9-4RA" secondAttribute="top" id="AdV-NL-x1c"/>
-                <constraint firstItem="hfV-D9-4RA" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="Tyq-ZP-0uJ"/>
-                <constraint firstItem="hfV-D9-4RA" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="biw-7T-hGm"/>
-                <constraint firstAttribute="bottom" secondItem="hfV-D9-4RA" secondAttribute="bottom" constant="33" id="pMc-ew-3II"/>
-            </constraints>
-            <nil key="simulatedBottomBarMetrics"/>
-            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
-            <connections>
-                <outlet property="baseView" destination="pPQ-tv-M04" id="g36-p2-WKr"/>
-                <outlet property="judgeButton" destination="a7T-m6-cO3" id="iNa-m8-fej"/>
-                <outlet property="lineView" destination="C3c-hV-10p" id="feE-N6-23a"/>
-                <outlet property="lineViewLeft" destination="vrQ-K4-VVb" id="6zN-xC-hNi"/>
-                <outlet property="settingButton" destination="p8P-5R-8Rj" id="TAu-gf-cnz"/>
-            </connections>
-            <point key="canvasLocation" x="542.75362318840587" y="-44.866071428571423"/>
-        </view>
-    </objects>
-    <resources>
-        <image name="cloud_cancle" width="26" height="26"/>
-        <systemColor name="systemBackgroundColor">
-            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-        </systemColor>
-    </resources>
-</document>

+ 0 - 36
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/SettingPageView.h

@@ -1,36 +0,0 @@
-//
-//  SettingPageView.h
-//  MidiPlayer
-//
-//  Created by Kyle on 2021/12/7.
-//
-
-#import <UIKit/UIKit.h>
-#import "KSCloudSettingView.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-typedef void(^SettingCallback)(CLOUDSETTING_TYPE type, BOOL isOn);
-
-@interface SettingPageView : UIView
-
-@property (nonatomic, assign) BOOL eyeProtect;   // 护眼模式
-
-@property (nonatomic, assign) BOOL soundCheck;   // 校音提醒
-
-@property (nonatomic, assign) BOOL cameraOn;     // 摄像头开关
-
-@property (nonatomic, assign) BOOL repeatOn;     // 循环播放
-
-@property (nonatomic, assign) BOOL showFinger;   // 显示指法
-
-
-+ (instancetype)shareInstance;
-
-- (void)querySettingConfig;
-
-- (void)settingCallback:(SettingCallback)callback;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 155
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/SettingPageView.m

@@ -1,155 +0,0 @@
-//
-//  SettingPageView.m
-//  MidiPlayer
-//
-//  Created by Kyle on 2021/12/7.
-//
-
-#import "SettingPageView.h"
-
-@interface SettingPageView ()
-
-@property (weak, nonatomic) IBOutlet UIButton *eyeButton;
-
-@property (weak, nonatomic) IBOutlet UIButton *judgeButton;
-
-@property (weak, nonatomic) IBOutlet UIButton *cameraButton;
-
-@property (weak, nonatomic) IBOutlet UIButton *repeatButton;
-
-@property (weak, nonatomic) IBOutlet UIButton *fingerButton;
-
-@property (nonatomic, copy) SettingCallback callback;
-
-@property (nonatomic, strong) NSMutableDictionary *configDict;
-
-@end
-
-@implementation SettingPageView
-
-+ (instancetype)shareInstance {
-    SettingPageView *view = [[[NSBundle mainBundle] loadNibNamed:@"SettingPageView" owner:nil options:nil] firstObject];
-    [view querySettingConfig];
-    return view;
-}
-- (void)defaultSetting {
-    self.eyeProtect = NO;
-    self.soundCheck = YES;
-    self.cameraOn = NO;
-    self.repeatOn = YES;
-    self.showFinger = YES;
-}
-
-- (void)querySettingConfig {
-    [self defaultSetting];
-    // 根据储存的配置项显示
-    NSDictionary *config = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"cloudConfig"];
-    self.configDict = [NSMutableDictionary dictionaryWithDictionary:config];
-    
-    self.eyeProtect = [[config valueForKey:@"eyeshield"] boolValue];
-    self.soundCheck = [[config valueForKey:@"soundCheck"] boolValue];
-    self.cameraOn = [[config valueForKey:@"cameraOn"] boolValue];
-    self.repeatOn = [[config valueForKey:@"repeatOn"] boolValue];
-    self.showFinger = [[config valueForKey:@"showFinger"] boolValue];
-    
-}
-
-- (void)synchronizeConfig {
-    [[NSUserDefaults standardUserDefaults] setObject:self.configDict forKey:@"cloudConfig"];
-    [[NSUserDefaults standardUserDefaults] synchronize];
-}
-
-- (void)settingCallback:(SettingCallback)callback {
-    if (callback) {
-        self.callback = callback;
-    }
-}
-#pragma mark ---- button action
-// 护眼模式
-- (IBAction)settingAction:(id)sender {
-    self.eyeProtect = !self.eyeProtect;
-    [self.configDict setValue:@(self.eyeProtect) forKey:@"eyeshield"];
-    [self synchronizeConfig];
-    if (self.callback) {
-        self.callback(CLOUDSETTING_TYPE_EYESHIELD, self.eyeProtect);
-    }
-}
-
-- (IBAction)judgeAction:(id)sender {
-    self.soundCheck = !self.soundCheck;
-    [self.configDict setValue:@(self.soundCheck) forKey:@"soundCheck"];
-    [self synchronizeConfig];
-    if (self.callback) {
-        self.callback(CLOUDSETTING_TYPE_SOUNDCHECK, self.soundCheck);
-    }
-}
-
-- (IBAction)cameraAction:(id)sender {
-    self.cameraOn = !self.cameraOn;
-    [self.configDict setValue:@(self.cameraOn) forKey:@"cameraOn"];
-    [self synchronizeConfig];
-    if (self.callback) {
-        self.callback(CLOUDSETTING_TYPE_CAMERA, self.cameraOn);
-    }
-}
-
-- (IBAction)repeatAction:(id)sender {
-    self.repeatOn = !self.repeatOn;
-    [self.configDict setValue:@(self.repeatOn) forKey:@"repeatOn"];
-    [self synchronizeConfig];
-    if (self.callback) {
-        self.callback(CLOUDSETTING_TYPE_REPEAT, self.repeatOn);
-    }
-}
-- (IBAction)showFingerAction:(id)sender {
-    self.showFinger = !self.showFinger;
-    [self.configDict setValue:@(self.showFinger) forKey:@"showFinger"];
-    [self synchronizeConfig];
-    if (self.callback) {
-        self.callback(CLOUDSETTING_TYPE_FINGER, self.showFinger);
-    }
-}
-
-#pragma mark ----  setter
-- (void)setEyeProtect:(BOOL)eyeProtect {
-    _eyeProtect = eyeProtect;
-    NSString *imageName = eyeProtect ? @"switch_on" : @"switch_off";
-    [self.eyeButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
-    
-}
-
-- (void)setSoundCheck:(BOOL)soundCheck {
-    _soundCheck = soundCheck;
-    NSString *imageName = soundCheck ? @"switch_on" : @"switch_off";
-    [self.judgeButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
-}
-
-- (void)setCameraOn:(BOOL)cameraOn {
-    _cameraOn = cameraOn;
-    NSString *imageName = cameraOn ? @"switch_on" : @"switch_off";
-    [self.cameraButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
-    
-}
-
-- (void)setRepeatOn:(BOOL)repeatOn {
-    _repeatOn = repeatOn;
-    NSString *imageName = repeatOn ? @"switch_on" : @"switch_off";
-    [self.repeatButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
-    
-}
-- (void)setShowFinger:(BOOL)showFinger {
-    _showFinger = showFinger;
-    NSString *imageName = showFinger ? @"switch_on" : @"switch_off";
-    [self.fingerButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
-    
-}
-/*
-// Only override drawRect: if you perform custom drawing.
-// An empty implementation adversely affects performance during animation.
-- (void)drawRect:(CGRect)rect {
-    // Drawing code
-}
-*/
-
-
-@end

+ 0 - 190
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SettingView/SettingPageView.xib

@@ -1,190 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
-    <device id="retina6_1" orientation="portrait" appearance="light"/>
-    <dependencies>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
-        <capability name="System colors in document resources" minToolsVersion="11.0"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <objects>
-        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
-        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="SettingPageView">
-            <rect key="frame" x="0.0" y="0.0" width="414" height="339"/>
-            <autoresizingMask key="autoresizingMask"/>
-            <subviews>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="TPz-Lt-ID7">
-                    <rect key="frame" x="0.0" y="0.0" width="414" height="68"/>
-                    <subviews>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="护眼模式" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hjM-RO-Jsw">
-                            <rect key="frame" x="25" y="25" width="62" height="18"/>
-                            <fontDescription key="fontDescription" type="system" pointSize="15"/>
-                            <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="md8-79-tRj">
-                            <rect key="frame" x="342" y="0.0" width="47" height="68"/>
-                            <state key="normal" image="switch_off"/>
-                            <connections>
-                                <action selector="settingAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="DLH-pG-G3y"/>
-                            </connections>
-                        </button>
-                    </subviews>
-                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                    <constraints>
-                        <constraint firstAttribute="bottom" secondItem="md8-79-tRj" secondAttribute="bottom" id="atg-yD-lBK"/>
-                        <constraint firstItem="hjM-RO-Jsw" firstAttribute="leading" secondItem="TPz-Lt-ID7" secondAttribute="leading" constant="25" id="cTH-K0-35d"/>
-                        <constraint firstAttribute="trailing" secondItem="md8-79-tRj" secondAttribute="trailing" constant="25" id="jNX-dW-Dfb"/>
-                        <constraint firstItem="hjM-RO-Jsw" firstAttribute="centerY" secondItem="TPz-Lt-ID7" secondAttribute="centerY" id="nAZ-Pi-kF0"/>
-                        <constraint firstItem="md8-79-tRj" firstAttribute="top" secondItem="TPz-Lt-ID7" secondAttribute="top" id="r0k-ZD-CFS"/>
-                    </constraints>
-                </view>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wq8-rv-zdW">
-                    <rect key="frame" x="0.0" y="68" width="414" height="67.5"/>
-                    <subviews>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="校音提醒" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XQy-R8-0mY">
-                            <rect key="frame" x="25" y="24.5" width="62" height="18"/>
-                            <fontDescription key="fontDescription" type="system" pointSize="15"/>
-                            <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="3ZL-a9-mCu">
-                            <rect key="frame" x="342" y="0.0" width="47" height="67.5"/>
-                            <state key="normal" image="switch_off"/>
-                            <connections>
-                                <action selector="judgeAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="ZHW-it-NZn"/>
-                            </connections>
-                        </button>
-                    </subviews>
-                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                    <constraints>
-                        <constraint firstItem="3ZL-a9-mCu" firstAttribute="top" secondItem="wq8-rv-zdW" secondAttribute="top" id="1q5-mT-g66"/>
-                        <constraint firstAttribute="trailing" secondItem="3ZL-a9-mCu" secondAttribute="trailing" constant="25" id="Nbd-3b-VGJ"/>
-                        <constraint firstAttribute="bottom" secondItem="3ZL-a9-mCu" secondAttribute="bottom" id="YOl-mQ-kEz"/>
-                        <constraint firstItem="XQy-R8-0mY" firstAttribute="centerY" secondItem="wq8-rv-zdW" secondAttribute="centerY" id="aIc-ve-n5V"/>
-                        <constraint firstItem="XQy-R8-0mY" firstAttribute="leading" secondItem="wq8-rv-zdW" secondAttribute="leading" constant="25" id="zVu-mo-rhz"/>
-                    </constraints>
-                </view>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="z67-Ah-wa8">
-                    <rect key="frame" x="0.0" y="135.5" width="414" height="68"/>
-                    <subviews>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="摄像头" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HW4-ck-jy7">
-                            <rect key="frame" x="25" y="25" width="46" height="18"/>
-                            <fontDescription key="fontDescription" type="system" pointSize="15"/>
-                            <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="7rE-UU-UnI">
-                            <rect key="frame" x="342" y="0.0" width="47" height="68"/>
-                            <state key="normal" image="switch_off"/>
-                            <connections>
-                                <action selector="cameraAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="lHw-xs-DUp"/>
-                            </connections>
-                        </button>
-                    </subviews>
-                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                    <constraints>
-                        <constraint firstAttribute="trailing" secondItem="7rE-UU-UnI" secondAttribute="trailing" constant="25" id="1Y2-MB-VhC"/>
-                        <constraint firstItem="HW4-ck-jy7" firstAttribute="leading" secondItem="z67-Ah-wa8" secondAttribute="leading" constant="25" id="3Cb-e9-Nij"/>
-                        <constraint firstAttribute="bottom" secondItem="7rE-UU-UnI" secondAttribute="bottom" id="9i1-IH-YVS"/>
-                        <constraint firstItem="7rE-UU-UnI" firstAttribute="top" secondItem="z67-Ah-wa8" secondAttribute="top" id="Kgw-at-gJp"/>
-                        <constraint firstItem="HW4-ck-jy7" firstAttribute="centerY" secondItem="z67-Ah-wa8" secondAttribute="centerY" id="mBn-qQ-Prm"/>
-                    </constraints>
-                </view>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="zDJ-Vf-KV4">
-                    <rect key="frame" x="0.0" y="203.5" width="414" height="67.5"/>
-                    <subviews>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="循环播放" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Gnw-gE-pov">
-                            <rect key="frame" x="25" y="25" width="61.5" height="18"/>
-                            <fontDescription key="fontDescription" type="system" pointSize="15"/>
-                            <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="pfs-HS-b09">
-                            <rect key="frame" x="342" y="0.0" width="47" height="67.5"/>
-                            <state key="normal" image="switch_off"/>
-                            <connections>
-                                <action selector="repeatAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="4HJ-j5-F3s"/>
-                            </connections>
-                        </button>
-                    </subviews>
-                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                    <constraints>
-                        <constraint firstItem="pfs-HS-b09" firstAttribute="top" secondItem="zDJ-Vf-KV4" secondAttribute="top" id="4Aj-F1-5Xb"/>
-                        <constraint firstAttribute="trailing" secondItem="pfs-HS-b09" secondAttribute="trailing" constant="25" id="E64-KK-WZD"/>
-                        <constraint firstItem="Gnw-gE-pov" firstAttribute="leading" secondItem="zDJ-Vf-KV4" secondAttribute="leading" constant="25" id="JpA-ig-FAM"/>
-                        <constraint firstAttribute="bottom" secondItem="pfs-HS-b09" secondAttribute="bottom" id="kH0-d7-2UN"/>
-                        <constraint firstItem="Gnw-gE-pov" firstAttribute="centerY" secondItem="zDJ-Vf-KV4" secondAttribute="centerY" id="sJp-ZW-jHQ"/>
-                    </constraints>
-                </view>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="V10-3p-7eW">
-                    <rect key="frame" x="0.0" y="271" width="414" height="68"/>
-                    <subviews>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="显示指法" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kKb-ZC-FIu">
-                            <rect key="frame" x="25" y="25" width="61.5" height="18"/>
-                            <fontDescription key="fontDescription" type="system" pointSize="15"/>
-                            <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="gvo-y6-Ae5">
-                            <rect key="frame" x="342" y="0.0" width="47" height="68"/>
-                            <state key="normal" image="switch_off"/>
-                            <connections>
-                                <action selector="showFingerAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="VBb-pJ-HhL"/>
-                            </connections>
-                        </button>
-                    </subviews>
-                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                    <constraints>
-                        <constraint firstItem="gvo-y6-Ae5" firstAttribute="top" secondItem="V10-3p-7eW" secondAttribute="top" id="MXk-Nd-kGY"/>
-                        <constraint firstAttribute="trailing" secondItem="gvo-y6-Ae5" secondAttribute="trailing" constant="25" id="OAR-r7-irb"/>
-                        <constraint firstItem="kKb-ZC-FIu" firstAttribute="leading" secondItem="V10-3p-7eW" secondAttribute="leading" constant="25" id="bPa-kw-nNs"/>
-                        <constraint firstItem="kKb-ZC-FIu" firstAttribute="centerY" secondItem="V10-3p-7eW" secondAttribute="centerY" id="dO2-0S-Psh"/>
-                        <constraint firstAttribute="bottom" secondItem="gvo-y6-Ae5" secondAttribute="bottom" id="uxT-ep-RPh"/>
-                    </constraints>
-                </view>
-            </subviews>
-            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-            <constraints>
-                <constraint firstAttribute="trailing" secondItem="wq8-rv-zdW" secondAttribute="trailing" id="6wM-KH-uQK"/>
-                <constraint firstItem="zDJ-Vf-KV4" firstAttribute="height" secondItem="TPz-Lt-ID7" secondAttribute="height" id="Bhi-bK-WDf"/>
-                <constraint firstAttribute="bottom" secondItem="V10-3p-7eW" secondAttribute="bottom" id="CxM-Pd-ssC"/>
-                <constraint firstItem="wq8-rv-zdW" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="Erw-uP-QV5"/>
-                <constraint firstItem="TPz-Lt-ID7" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="HI5-MG-dPY"/>
-                <constraint firstItem="z67-Ah-wa8" firstAttribute="height" secondItem="TPz-Lt-ID7" secondAttribute="height" id="ILl-Ih-a4Q"/>
-                <constraint firstAttribute="trailing" secondItem="zDJ-Vf-KV4" secondAttribute="trailing" id="Irg-ee-Bmh"/>
-                <constraint firstItem="zDJ-Vf-KV4" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="KYH-Mi-Qp3"/>
-                <constraint firstAttribute="trailing" secondItem="TPz-Lt-ID7" secondAttribute="trailing" id="SJw-JV-J1f"/>
-                <constraint firstItem="V10-3p-7eW" firstAttribute="height" secondItem="TPz-Lt-ID7" secondAttribute="height" id="Uzr-qa-gr5"/>
-                <constraint firstItem="V10-3p-7eW" firstAttribute="top" secondItem="zDJ-Vf-KV4" secondAttribute="bottom" id="YLv-Yy-M9a"/>
-                <constraint firstItem="wq8-rv-zdW" firstAttribute="top" secondItem="TPz-Lt-ID7" secondAttribute="bottom" id="fhn-gJ-GfI"/>
-                <constraint firstItem="z67-Ah-wa8" firstAttribute="top" secondItem="wq8-rv-zdW" secondAttribute="bottom" id="glK-Rc-hfc"/>
-                <constraint firstAttribute="trailing" secondItem="V10-3p-7eW" secondAttribute="trailing" id="hal-ff-Oaq"/>
-                <constraint firstItem="wq8-rv-zdW" firstAttribute="height" secondItem="TPz-Lt-ID7" secondAttribute="height" id="nJP-su-1KL"/>
-                <constraint firstItem="z67-Ah-wa8" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="uL5-Ms-8Sr"/>
-                <constraint firstItem="TPz-Lt-ID7" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="uTR-sy-eZx"/>
-                <constraint firstAttribute="trailing" secondItem="z67-Ah-wa8" secondAttribute="trailing" id="ugX-F6-s7a"/>
-                <constraint firstItem="zDJ-Vf-KV4" firstAttribute="top" secondItem="z67-Ah-wa8" secondAttribute="bottom" id="vFX-hG-wz7"/>
-                <constraint firstItem="V10-3p-7eW" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="xYU-9u-VUc"/>
-                <constraint firstAttribute="bottom" secondItem="V10-3p-7eW" secondAttribute="bottom" id="yCa-rq-sI7"/>
-            </constraints>
-            <nil key="simulatedTopBarMetrics"/>
-            <nil key="simulatedBottomBarMetrics"/>
-            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
-            <connections>
-                <outlet property="cameraButton" destination="7rE-UU-UnI" id="4Ma-2q-NLS"/>
-                <outlet property="eyeButton" destination="md8-79-tRj" id="jRV-jI-RIg"/>
-                <outlet property="fingerButton" destination="gvo-y6-Ae5" id="guC-Hj-VS6"/>
-                <outlet property="judgeButton" destination="3ZL-a9-mCu" id="Cn6-tM-eEY"/>
-                <outlet property="repeatButton" destination="pfs-HS-b09" id="qeg-gI-XyC"/>
-            </connections>
-            <point key="canvasLocation" x="76.811594202898561" y="37.165178571428569"/>
-        </view>
-    </objects>
-    <resources>
-        <image name="switch_off" width="47" height="24"/>
-        <systemColor name="systemBackgroundColor">
-            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-        </systemColor>
-    </resources>
-</document>

+ 0 - 43
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SoundCheckView/SoundCheckView.h

@@ -1,43 +0,0 @@
-//
-//  SoundCheckView.h
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/13.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-typedef NS_ENUM(NSInteger, CLOSEACTION) {
-    CLOSEACTION_SKIP,
-    CLOSEACTION_CLOSECHECK,
-    CLOSEACTION_SUCCESS,
-};
-
-typedef NS_ENUM(NSInteger, LIGHTDISPLAY) {
-    LIGHTDISPLAY_LOW,   // 频率低了
-    LIGHTDISPLAY_RIGHT, // 频率正常
-    LIGHTDISPLAY_HIGH,  // 频率高了
-};
-
-typedef void(^SoundCheckCallback)(CLOSEACTION action);
-
-@interface SoundCheckView : UIView
-
-@property (nonatomic, assign) NSInteger pitch;
-
-@property (nonatomic, copy) SoundCheckCallback callback;
-
-+ (instancetype)shareInstance;
-
-- (void)configSoundCheckWithSubjectId:(NSString *)subjectId callback:(SoundCheckCallback)callback;
-
-- (void)showSuccessCheckEnd;
-
-- (void)showLightDisplay:(LIGHTDISPLAY)type;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 153
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SoundCheckView/SoundCheckView.m

@@ -1,153 +0,0 @@
-//
-//  SoundCheckView.m
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/13.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import "SoundCheckView.h"
-#import "LFPopupMenu.h"
-
-@interface SoundCheckView ()
-
-@property (weak, nonatomic) IBOutlet UIImageView *leftDot;
-
-@property (weak, nonatomic) IBOutlet UIImageView *midDot;
-
-@property (weak, nonatomic) IBOutlet UIImageView *rightDot;
-
-
-@property (weak, nonatomic) IBOutlet UIImageView *staffImageView;
-
-
-@end
-
-@implementation SoundCheckView
-
-+ (instancetype)shareInstance {
-    SoundCheckView *view = [[[NSBundle mainBundle] loadNibNamed:@"SoundCheckView" owner:nil options:nil] firstObject];
-    return view;
-}
-- (void)configSoundCheckWithSubjectId:(NSString *)subjectId callback:(SoundCheckCallback)callback {
-    if (callback) {
-        self.callback = callback;
-    }
-    [self configStaffImageWithSubjectId:subjectId];
-}
-
-- (void)configStaffImageWithSubjectId:(NSString *)subjectId {
-    NSString *imgName = @"";
-    if ([subjectId isEqualToString:@"12"] || [subjectId isEqualToString:@"4"]) { // 小号 || 单簧管
-        imgName = @"staff_C5";
-        self.pitch = 60;
-    }
-    else if ([subjectId isEqualToString:@"14"] || [subjectId isEqualToString:@"15"]) { // 长号 || 上低音号
-        imgName = @"staff_S";
-        self.pitch = 34;
-    }
-    else if ([subjectId isEqualToString:@"13"]) { // 圆号
-        imgName = @"staff_F";
-        self.pitch = 53;
-    }
-    else if ([subjectId isEqualToString:@"5"] || [subjectId isEqualToString:@"6"]) { // sax
-        imgName = @"staff_C5(C)";
-        self.pitch = 60;
-    }
-    else if ([subjectId isEqualToString:@"120"]) { // 竖笛
-        imgName = @"staff_A5";
-        self.pitch = 69;
-    }
-    else { // 剩余声部
-        imgName = @"staff_b-14";
-        self.pitch = 58;
-    }
-    [self.staffImageView setImage:[UIImage imageNamed:imgName]];
-}
-
-
-- (void)resetImage {
-    [self.leftDot setImage:[UIImage imageNamed:@"emptyDot"]];
-    [self.midDot setImage:[UIImage imageNamed:@"emptyDot"]];
-    [self.rightDot setImage:[UIImage imageNamed:@"emptyDot"]];
-}
-- (void)showLightDisplay:(LIGHTDISPLAY)type {
-    [self resetImage];
-    switch (type) {
-        case LIGHTDISPLAY_LOW:
-        {
-            [self.leftDot setImage:[UIImage imageNamed:@"sound_wrong"]];
-        }
-            break;
-        case LIGHTDISPLAY_RIGHT:
-        {
-            [self.midDot setImage:[UIImage imageNamed:@"sound_right"]];
-        }
-            break;
-        case LIGHTDISPLAY_HIGH:
-        {
-            [self.rightDot setImage:[UIImage imageNamed:@"sound_wrong"]];
-        }
-            break;
-        default:
-            break;
-    }
-}
-
-- (IBAction)cancleAction:(id)sender {
-    [self closeViewWithType:CLOSEACTION_SKIP];
-}
-
-- (IBAction)skipButtonAction:(UIButton *)sender {
-    [self showTipsView:sender];
-}
-
-- (void)showTipsView:(UIButton *)button {
-    MJWeakSelf;
-    LFPopupMenuItem *item1 = [LFPopupMenuItem createWithTitle:@"跳过本次" image:nil action:^{
-        // 跳过
-        [weakSelf closeViewWithType:CLOSEACTION_SKIP];
-    }];
-    LFPopupMenuItem *item2 = [LFPopupMenuItem createWithTitle:@"关闭校音" image:nil action:^{
-        // 关闭校音
-        [weakSelf closeViewWithType:CLOSEACTION_CLOSECHECK];
-    }];
-    
-    LFPopupMenu *menu = [[LFPopupMenu alloc] init];
-    menu.needBorder = YES;
-    menu.rowHeight = 40.0f;
-    menu.minWidth = 76;
-    menu.textColor = HexRGB(0x333333);
-    menu.textFont = [UIFont systemFontOfSize:12.0f weight:UIFontWeightMedium];
-    
-    [menu configWithItems:@[item1,item2]];
-    [menu showArrowToView:button];
-}
-
-- (void)closeViewWithType:(CLOSEACTION)type {
-    [self removeFromSuperview];
-    if (self.callback) {
-        self.callback(type);
-    }
-}
-
-- (void)successCheckCallback {
-    [self removeFromSuperview];
-    if (self.callback) {
-        self.callback(CLOSEACTION_SUCCESS);
-    }
-}
-
-- (void)showSuccessCheckEnd {
-    [self successCheckCallback];
-}
-
-/*
-// Only override drawRect: if you perform custom drawing.
-// An empty implementation adversely affects performance during animation.
-- (void)drawRect:(CGRect)rect {
-    // Drawing code
-}
-*/
-
-@end

+ 0 - 177
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SoundCheckView/SoundCheckView.xib

@@ -1,177 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
-    <device id="retina6_1" orientation="portrait" appearance="light"/>
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
-        <capability name="System colors in document resources" minToolsVersion="11.0"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <objects>
-        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
-        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="SoundCheckView">
-            <rect key="frame" x="0.0" y="0.0" width="907" height="422"/>
-            <autoresizingMask key="autoresizingMask"/>
-            <subviews>
-                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="redraw" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="soundCheck_bg" translatesAutoresizingMaskIntoConstraints="NO" id="DE8-bH-WR0">
-                    <rect key="frame" x="0.0" y="0.0" width="907" height="422"/>
-                </imageView>
-                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Q7x-bJ-NJm">
-                    <rect key="frame" x="10" y="10" width="44" height="44"/>
-                    <constraints>
-                        <constraint firstAttribute="height" constant="44" id="8NW-Mp-yYf"/>
-                        <constraint firstAttribute="width" constant="44" id="a1E-FX-ymR"/>
-                    </constraints>
-                    <state key="normal" image="cloudback_white"/>
-                    <connections>
-                        <action selector="cancleAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="r6I-rZ-iMK"/>
-                    </connections>
-                </button>
-                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="cloud_music" translatesAutoresizingMaskIntoConstraints="NO" id="lv2-Oo-rwG">
-                    <rect key="frame" x="26" y="64" width="855" height="308"/>
-                    <constraints>
-                        <constraint firstAttribute="width" secondItem="lv2-Oo-rwG" secondAttribute="height" multiplier="286:103" id="czf-na-sj7"/>
-                    </constraints>
-                </imageView>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="FA0-6u-T0j">
-                    <rect key="frame" x="206.5" y="40" width="494" height="314"/>
-                    <subviews>
-                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="cloud_blackboard" translatesAutoresizingMaskIntoConstraints="NO" id="H1h-j5-1lu">
-                            <rect key="frame" x="0.0" y="0.0" width="494" height="314"/>
-                        </imageView>
-                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="OCq-9O-8fJ">
-                            <rect key="frame" x="172" y="227" width="150" height="50"/>
-                            <subviews>
-                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="emptyDot" translatesAutoresizingMaskIntoConstraints="NO" id="hdh-04-p1S">
-                                    <rect key="frame" x="15" y="10" width="30" height="30"/>
-                                </imageView>
-                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="emptyDot" translatesAutoresizingMaskIntoConstraints="NO" id="LE9-0Y-6d3">
-                                    <rect key="frame" x="60" y="10" width="30" height="30"/>
-                                    <constraints>
-                                        <constraint firstAttribute="width" constant="30" id="ldo-1V-e4N"/>
-                                        <constraint firstAttribute="height" constant="30" id="mFT-3S-Kpi"/>
-                                    </constraints>
-                                </imageView>
-                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="emptyDot" translatesAutoresizingMaskIntoConstraints="NO" id="0B9-od-SoC">
-                                    <rect key="frame" x="105" y="10" width="30" height="30"/>
-                                </imageView>
-                            </subviews>
-                            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                            <constraints>
-                                <constraint firstItem="LE9-0Y-6d3" firstAttribute="centerY" secondItem="hdh-04-p1S" secondAttribute="centerY" id="3yP-Y6-H1v"/>
-                                <constraint firstItem="LE9-0Y-6d3" firstAttribute="leading" secondItem="hdh-04-p1S" secondAttribute="trailing" constant="15" id="8ac-fR-jUz"/>
-                                <constraint firstItem="LE9-0Y-6d3" firstAttribute="centerY" secondItem="OCq-9O-8fJ" secondAttribute="centerY" id="GwT-jl-9Ic"/>
-                                <constraint firstAttribute="width" constant="150" id="OUm-fX-CBP"/>
-                                <constraint firstAttribute="height" constant="50" id="VUq-ud-m3T"/>
-                                <constraint firstItem="LE9-0Y-6d3" firstAttribute="centerX" secondItem="OCq-9O-8fJ" secondAttribute="centerX" id="dlM-dP-Ta5"/>
-                                <constraint firstItem="0B9-od-SoC" firstAttribute="centerY" secondItem="hdh-04-p1S" secondAttribute="centerY" id="fx0-EP-KhH"/>
-                                <constraint firstItem="0B9-od-SoC" firstAttribute="leading" secondItem="LE9-0Y-6d3" secondAttribute="trailing" constant="15" id="sFv-Gb-Rk8"/>
-                            </constraints>
-                        </view>
-                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="staff_C" translatesAutoresizingMaskIntoConstraints="NO" id="dw5-YO-FzD">
-                            <rect key="frame" x="127" y="127" width="240" height="70"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="70" id="KWY-Tw-37n"/>
-                                <constraint firstAttribute="width" constant="240" id="LKn-az-RPR"/>
-                            </constraints>
-                        </imageView>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="请演奏直到中间绿灯亮起" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cKL-Ai-eDg">
-                            <rect key="frame" x="168" y="197" width="158" height="20"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="20" id="f3w-ar-xHb"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                            <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                    </subviews>
-                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                    <constraints>
-                        <constraint firstItem="dw5-YO-FzD" firstAttribute="centerX" secondItem="FA0-6u-T0j" secondAttribute="centerX" id="8TP-hN-kB8"/>
-                        <constraint firstAttribute="trailing" secondItem="H1h-j5-1lu" secondAttribute="trailing" id="Am4-Fd-A69"/>
-                        <constraint firstAttribute="width" secondItem="FA0-6u-T0j" secondAttribute="height" multiplier="494:314" id="Ok6-HV-AWa"/>
-                        <constraint firstItem="OCq-9O-8fJ" firstAttribute="centerX" secondItem="FA0-6u-T0j" secondAttribute="centerX" id="QpT-bj-z7Z"/>
-                        <constraint firstItem="H1h-j5-1lu" firstAttribute="leading" secondItem="FA0-6u-T0j" secondAttribute="leading" id="U0E-AZ-7LF"/>
-                        <constraint firstItem="H1h-j5-1lu" firstAttribute="top" secondItem="FA0-6u-T0j" secondAttribute="top" id="a9M-ya-ppz"/>
-                        <constraint firstAttribute="bottom" secondItem="H1h-j5-1lu" secondAttribute="bottom" id="evf-rJ-FT1"/>
-                        <constraint firstItem="OCq-9O-8fJ" firstAttribute="top" secondItem="cKL-Ai-eDg" secondAttribute="bottom" constant="10" id="gbJ-iC-jmF"/>
-                        <constraint firstItem="cKL-Ai-eDg" firstAttribute="centerX" secondItem="FA0-6u-T0j" secondAttribute="centerX" id="t6D-6o-Z0l"/>
-                        <constraint firstItem="cKL-Ai-eDg" firstAttribute="top" secondItem="dw5-YO-FzD" secondAttribute="bottom" id="teU-wM-41k"/>
-                    </constraints>
-                </view>
-                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="check_headPhone" translatesAutoresizingMaskIntoConstraints="NO" id="YlK-H1-rfX">
-                    <rect key="frame" x="236.5" y="287" width="95" height="135"/>
-                    <constraints>
-                        <constraint firstAttribute="width" secondItem="YlK-H1-rfX" secondAttribute="height" multiplier="19:27" id="dm0-fU-LSm"/>
-                    </constraints>
-                </imageView>
-                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="跳过本次" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8Dy-Po-zbc">
-                    <rect key="frame" x="785" y="24" width="74" height="22"/>
-                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="18"/>
-                    <nil key="textColor"/>
-                    <nil key="highlightedColor"/>
-                </label>
-                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="down_arrow" translatesAutoresizingMaskIntoConstraints="NO" id="Gze-Pn-Alp">
-                    <rect key="frame" x="864" y="30" width="14" height="10"/>
-                </imageView>
-                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0Z7-6c-ASS">
-                    <rect key="frame" x="785" y="15" width="93" height="40"/>
-                    <constraints>
-                        <constraint firstAttribute="height" constant="40" id="uX4-r8-D35"/>
-                    </constraints>
-                    <connections>
-                        <action selector="skipButtonAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="W3C-fk-Wbk"/>
-                    </connections>
-                </button>
-            </subviews>
-            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-            <constraints>
-                <constraint firstItem="Gze-Pn-Alp" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="30" id="3yW-2D-HEN"/>
-                <constraint firstAttribute="trailing" secondItem="lv2-Oo-rwG" secondAttribute="trailing" constant="26" id="6ma-Pu-Tw8"/>
-                <constraint firstItem="YlK-H1-rfX" firstAttribute="leading" secondItem="FA0-6u-T0j" secondAttribute="leading" constant="30" id="75t-zn-cHr"/>
-                <constraint firstItem="Gze-Pn-Alp" firstAttribute="leading" secondItem="8Dy-Po-zbc" secondAttribute="trailing" constant="5" id="8hF-04-ruI"/>
-                <constraint firstItem="Q7x-bJ-NJm" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="Dku-jN-vJj"/>
-                <constraint firstItem="Gze-Pn-Alp" firstAttribute="centerY" secondItem="0Z7-6c-ASS" secondAttribute="centerY" id="K5X-ql-gIC"/>
-                <constraint firstItem="0Z7-6c-ASS" firstAttribute="leading" secondItem="8Dy-Po-zbc" secondAttribute="leading" id="KHT-b9-YyP"/>
-                <constraint firstItem="lv2-Oo-rwG" firstAttribute="top" secondItem="Q7x-bJ-NJm" secondAttribute="bottom" constant="10" id="Mgh-1M-5db"/>
-                <constraint firstItem="FA0-6u-T0j" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="Nly-GO-YZc"/>
-                <constraint firstItem="lv2-Oo-rwG" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="26" id="SVo-s8-PUO"/>
-                <constraint firstAttribute="trailing" secondItem="DE8-bH-WR0" secondAttribute="trailing" id="TAz-Gn-46Q"/>
-                <constraint firstItem="Gze-Pn-Alp" firstAttribute="trailing" secondItem="0Z7-6c-ASS" secondAttribute="trailing" id="Xt5-Z5-MkV"/>
-                <constraint firstItem="DE8-bH-WR0" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="aK9-i0-r7N"/>
-                <constraint firstAttribute="trailing" secondItem="Gze-Pn-Alp" secondAttribute="trailing" constant="29" id="bYk-qU-2I5"/>
-                <constraint firstItem="OCq-9O-8fJ" firstAttribute="top" secondItem="YlK-H1-rfX" secondAttribute="top" constant="-20" id="bvs-3l-u7h"/>
-                <constraint firstItem="DE8-bH-WR0" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="fFs-mc-dm4"/>
-                <constraint firstItem="FA0-6u-T0j" firstAttribute="top" secondItem="Q7x-bJ-NJm" secondAttribute="top" constant="30" id="feU-Hk-QNn"/>
-                <constraint firstAttribute="bottom" secondItem="DE8-bH-WR0" secondAttribute="bottom" id="jwC-i3-ICT"/>
-                <constraint firstItem="Gze-Pn-Alp" firstAttribute="centerY" secondItem="8Dy-Po-zbc" secondAttribute="centerY" id="k9w-ug-51F"/>
-                <constraint firstAttribute="bottom" secondItem="YlK-H1-rfX" secondAttribute="bottom" id="laE-no-0I1"/>
-                <constraint firstItem="Q7x-bJ-NJm" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="10" id="n47-CT-3ga"/>
-            </constraints>
-            <nil key="simulatedTopBarMetrics"/>
-            <nil key="simulatedBottomBarMetrics"/>
-            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
-            <connections>
-                <outlet property="leftDot" destination="hdh-04-p1S" id="Mz0-uF-8Nh"/>
-                <outlet property="midDot" destination="LE9-0Y-6d3" id="Wop-lD-frP"/>
-                <outlet property="rightDot" destination="0B9-od-SoC" id="GRI-oC-Mem"/>
-                <outlet property="staffImageView" destination="dw5-YO-FzD" id="g6B-dA-72c"/>
-            </connections>
-            <point key="canvasLocation" x="280.43478260869568" y="-74.330357142857139"/>
-        </view>
-    </objects>
-    <resources>
-        <image name="check_headPhone" width="95" height="135"/>
-        <image name="cloud_blackboard" width="494" height="314"/>
-        <image name="cloud_music" width="735" height="206"/>
-        <image name="cloudback_white" width="32" height="32"/>
-        <image name="down_arrow" width="14" height="10"/>
-        <image name="emptyDot" width="30" height="30"/>
-        <image name="soundCheck_bg" width="812" height="375"/>
-        <image name="staff_C" width="985.5" height="286.5"/>
-        <systemColor name="systemBackgroundColor">
-            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-        </systemColor>
-    </resources>
-</document>

+ 0 - 38
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SpeedSlider/KSSliderView.h

@@ -1,38 +0,0 @@
-//
-//  KSSliderView.h
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/13.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-@protocol KSSliderDelegate <NSObject>
-
-@optional
-
-- (void)rateChangeAction:(NSInteger)rate;
-- (void)beginSwip;
-- (void)endSwip;
-
-@end
-
-@interface KSSliderView : UIView
-
-@property (nonatomic, assign) BOOL isVertical;
-
-@property (strong, nonatomic) NSNumberFormatter *numberFormatter;
-@property (nonatomic, assign) CGFloat minValue;
-@property (nonatomic, assign) CGFloat maxValue;
-@property (nonatomic, strong) UIColor *minimumTrackTintColor;
-@property (nonatomic, strong) UIColor *maxmumTrackTintColor;
-@property (nonatomic, assign) NSInteger rateValue;
-
-@property (nonatomic, unsafe_unretained)id<KSSliderDelegate>delegate;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 154
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SpeedSlider/KSSliderView.m

@@ -1,154 +0,0 @@
-//
-//  KSSliderView.m
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/13.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import "KSSliderView.h"
-#import "KSTrackingSlider.h"
-
-@interface KSSliderView ()<KSTrackingSliderDelegate>
-
-@property (nonatomic, strong) UIButton *addButton; // 加
-
-@property (nonatomic, strong) UIButton *subtractButton; // 减
-
-@property (nonatomic, strong) KSTrackingSlider *sliderBar;
-
-@end
-
-@implementation KSSliderView
-
-- (instancetype)initWithFrame:(CGRect)frame {
-    self = [super initWithFrame:frame];
-    if (self) {
-        [self setUpWithFrame:frame];
-    }
-    return self;
-}
-
-- (void)setUpWithFrame:(CGRect)frame {
-    self.layer.cornerRadius = 5.0f;
-    NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
-    [formatter setNumberStyle:NSNumberFormatterDecimalStyle];
-    [formatter setRoundingMode:NSNumberFormatterRoundHalfUp];
-    [formatter setMaximumFractionDigits:0];
-    [formatter setMinimumFractionDigits:0];
-    _numberFormatter = formatter;
-    [self addButtons];
-    [self addSubview:self.sliderBar];
-}
-
-- (void)setRateValue:(NSInteger)rateValue {
-    _rateValue = rateValue;
-    self.sliderBar.value = rateValue;
-    if (self.delegate && [self.delegate respondsToSelector:@selector(rateChangeAction:)]) {
-        [self.delegate rateChangeAction:rateValue];
-    }
-}
-
-- (void)addButtons {
-    [self addSubview:self.addButton];
-    [self addSubview:self.subtractButton];
-}
-
-
-#pragma mark --- lazying
-
-- (UIButton *)addButton {
-    if (!_addButton) {
-        _addButton = [UIButton buttonWithType:UIButtonTypeCustom];
-        _addButton.frame = CGRectMake(5, 10, 40, 40);
-        [_addButton setImage:[UIImage imageNamed:@"img_speed_add"] forState:UIControlStateNormal];
-        [_addButton addTarget:self action:@selector(addValueAction:) forControlEvents:UIControlEventTouchUpInside];
-    }
-    return _addButton;
-}
-
-
-- (void)addValueAction:(UIButton *)sender {
-    self.rateValue = self.rateValue + 1;
-}
-
-- (UIButton *)subtractButton {
-    if (!_subtractButton) {
-        _subtractButton = [UIButton buttonWithType:UIButtonTypeCustom];
-        _subtractButton.frame = CGRectMake(5, CGRectGetHeight(self.frame) - 40, 40, 40);
-        [_subtractButton setImage:[UIImage imageNamed:@"img_speed_reduce"] forState:UIControlStateNormal];
-        [_subtractButton addTarget:self action:@selector(subtractAction:) forControlEvents:UIControlEventTouchUpInside];
-    }
-    return _subtractButton;
-}
-
-- (void)subtractAction:(UIButton *)sender {
-    self.rateValue = self.rateValue - 1;
-}
-
-- (KSTrackingSlider *)sliderBar {
-    if (!_sliderBar) {
-        CGFloat width = 160.0f;
-        CGFloat height = 50.0f;
-        _sliderBar = [[KSTrackingSlider alloc] initWithFrame:CGRectMake(height / 2.0f - width / 2.0f, width / 2.0f + 50 - height / 2.0f , width, height)];
-        _sliderBar.tintColor = HexRGB(0x01c1b5);
-        _sliderBar.delegate = self;
-        _sliderBar.minimumValue = 45;
-        _sliderBar.maximumValue = 270;
-    }
-    return _sliderBar;
-}
-- (void)currentValueOfSlider:(KSTrackingSlider *)slider {
-    self.rateValue = [_numberFormatter stringFromNumber:@(slider.value)].integerValue;
-}
-
-- (void)beginSwipSlider:(KSTrackingSlider *)slider {
-    if (self.delegate && [self.delegate respondsToSelector:@selector(beginSwip)]) {
-        [self.delegate beginSwip];
-    }
-}
-
-- (void)endSwipSlider:(KSTrackingSlider *)slider {
-    if (self.delegate && [self.delegate respondsToSelector:@selector(endSwip)]) {
-        [self.delegate endSwip];
-    }
-}
-
-- (void)setIsVertical:(BOOL)isVertical{
-    _isVertical = isVertical;
-    if (_isVertical == YES) {
-        self.sliderBar.transform = CGAffineTransformMakeRotation(-M_PI_2);
-
-    }else{
-        
-    }
-}
-- (void)setNumberFormatter:(NSNumberFormatter *)numberFormatter
-{
-    _numberFormatter = numberFormatter;
-}
-- (void)setMinValue:(CGFloat)minValue{
-    _minValue = minValue;
-    _sliderBar.minimumValue = minValue;
-}
-- (void)setMaxValue:(CGFloat)maxValue{
-    _maxValue = maxValue;
-    _sliderBar.maximumValue = maxValue;
-}
-- (void)setMinimumTrackTintColor:(UIColor *)minimumTrackTintColor{
-    _minimumTrackTintColor = minimumTrackTintColor;
-    _sliderBar.minimumTrackTintColor = minimumTrackTintColor;
-}
-- (void)setMaxmumTrackTintColor:(UIColor *)maxmumTrackTintColor{
-    _maxmumTrackTintColor = maxmumTrackTintColor;
-    _sliderBar.maximumTrackTintColor = maxmumTrackTintColor;
-}
-/*
-// Only override drawRect: if you perform custom drawing.
-// An empty implementation adversely affects performance during animation.
-- (void)drawRect:(CGRect)rect {
-    // Drawing code
-}
-*/
-
-@end

+ 0 - 29
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SpeedSlider/KSTrackingSlider.h

@@ -1,29 +0,0 @@
-//
-//  KSTrackingSlider.h
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/13.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@class KSTrackingSlider;
-
-@protocol KSTrackingSliderDelegate <NSObject>
-
-- (void)currentValueOfSlider:(KSTrackingSlider *_Nonnull)slider;
-- (void)beginSwipSlider:(KSTrackingSlider *_Nonnull)slider;
-- (void)endSwipSlider:(KSTrackingSlider *_Nonnull)slider;
-
-@end
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface KSTrackingSlider : UISlider
-
-@property (nonatomic, unsafe_unretained) id <KSTrackingSliderDelegate> delegate;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 70
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/SpeedSlider/KSTrackingSlider.m

@@ -1,70 +0,0 @@
-//
-//  KSTrackingSlider.m
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/13.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import "KSTrackingSlider.h"
-
-@implementation KSTrackingSlider
-
-- (instancetype)initWithFrame:(CGRect)frame {
-    self = [super initWithFrame:frame];
-    if (self) {
-        
-    }
-    return self;
-}
-
-#pragma mark --- subClassed
-
-- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
-    BOOL begin = [super beginTrackingWithTouch:touch withEvent:event];
-    if (begin) {
-        if ([self.delegate respondsToSelector:@selector(currentValueOfSlider:)]) {
-            [self.delegate currentValueOfSlider:self];
-        }
-        if ([self.delegate respondsToSelector:@selector(beginSwipSlider:)]) {
-            [self.delegate beginSwipSlider:self];
-        }
-    }
-    return begin;
-}
-
-- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
-{
-    BOOL continueTrack = [super continueTrackingWithTouch:touch withEvent:event];
-    if (continueTrack) {
-        if ([self.delegate respondsToSelector:@selector(currentValueOfSlider:)]) {
-            [self.delegate currentValueOfSlider:self];
-        }
-    }
-    return continueTrack;
-}
-- (void)cancelTrackingWithEvent:(UIEvent *)event
-{
-    [super cancelTrackingWithEvent:event];
-}
-
-- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
-{
-    [super endTrackingWithTouch:touch withEvent:event];
-    if ([self.delegate respondsToSelector:@selector(currentValueOfSlider:)]) {
-        [self.delegate currentValueOfSlider:self];
-    }
-    if ([self.delegate respondsToSelector:@selector(endSwipSlider:)]) {
-        [self.delegate endSwipSlider:self];
-    }
-}
-
-/*
-// Only override drawRect: if you perform custom drawing.
-// An empty implementation adversely affects performance during animation.
-- (void)drawRect:(CGRect)rect {
-    // Drawing code
-}
-*/
-
-@end

+ 0 - 25
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/StaffView/CloudControlButton.h

@@ -1,25 +0,0 @@
-//
-//  CloudControlButton.h
-//  MidiPlayer
-//
-//  Created by Kyle on 2021/12/6.
-//
-
-#import <UIKit/UIKit.h>
-
-NS_ASSUME_NONNULL_BEGIN
-@class CloudControlButton;
-
-typedef void(^ControlAction)(CloudControlButton *sender, BOOL isSelected);
-
-@interface CloudControlButton : UIView
-
-@property (nonatomic, assign) BOOL isSelected;
-
-+ (instancetype)createButtonWithImage:(NSString *)imageName selectImage:(NSString *)selectImage buttonTitle:(NSString *)buttonTitle selectTitle:(NSString *)selectTitle tag:(NSInteger)tag frame:(CGRect)frame callback:(ControlAction)callback;
-
-- (void)showSpeed:(NSInteger)speed;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 132
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/StaffView/CloudControlButton.m

@@ -1,132 +0,0 @@
-//
-//  CloudControlButton.m
-//  MidiPlayer
-//
-//  Created by Kyle on 2021/12/6.
-//
-
-#import "CloudControlButton.h"
-
-@interface CloudControlButton ()
-
-@property (nonatomic, strong) UILabel *titleLabel;
-
-@property (nonatomic, strong) UIButton *actionButton;
-
-@property (nonatomic, copy) ControlAction callback;
-
-@property (nonatomic, strong) NSString *buttonTitle;
-
-@property (nonatomic, strong) NSString *selectTitle;
-
-@property (nonatomic, strong) UILabel *speedLabel;
-@end
-
-@implementation CloudControlButton
-
-+ (instancetype)createButtonWithImage:(NSString *)imageName selectImage:(NSString *)selectImage buttonTitle:(NSString *)buttonTitle selectTitle:(NSString *)selectTitle tag:(NSInteger)tag frame:(CGRect)frame callback:(ControlAction)callback {
-    
-    CloudControlButton *controlButton = [[CloudControlButton alloc] initWithFrame:frame];
-    controlButton.tag = tag;
-    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
-    button.backgroundColor = [UIColor clearColor];
-    button.frame = CGRectMake(0, 0, frame.size.width, frame.size.width);
-    [button addTarget:controlButton action:@selector(buttonClickAction:) forControlEvents:UIControlEventTouchUpInside];
-    [button setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
-    [button setImage:[UIImage imageNamed:selectImage] forState:UIControlStateSelected];
-    [controlButton addSubview:button];
-    
-    [controlButton addSubview:controlButton.titleLabel];
-    controlButton.titleLabel.frame = CGRectMake(0, CGRectGetMaxX(button.frame) + 2, frame.size.width, 24);
-    controlButton.actionButton = button;
-    controlButton.buttonTitle = buttonTitle;
-    controlButton.selectTitle = selectTitle;
-    
-    controlButton.isSelected = NO;
-    if (callback) {
-        controlButton.callback = callback;
-    }
-    
-    return controlButton;
-}
-
-- (void)showSpeed:(NSInteger)speed {
-    if (!_speedLabel) {
-        UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
-        view.backgroundColor = UIColor.whiteColor;
-        view.layer.cornerRadius = 8.0f;
-        view.layer.borderColor = THEMECOLOR.CGColor;
-        view.layer.borderWidth = 1.0f;
-        [view addSubview:self.speedLabel];
-        [self addSubview:view];
-        
-        [view mas_makeConstraints:^(MASConstraintMaker *make) {
-            make.left.mas_equalTo(self.actionButton.mas_right).offset(-8);
-            make.top.mas_equalTo(self.actionButton.mas_top);
-            make.height.mas_equalTo(16.0f);
-        }];
-        
-        [self.speedLabel mas_makeConstraints:^(MASConstraintMaker *make) {
-            make.left.mas_equalTo(view.mas_left).offset(5);
-            make.right.mas_equalTo(view.mas_right).offset(-5);
-            make.centerY.mas_equalTo(view.mas_centerY);
-        }];
-
-    }
-    else {
-        
-    }
-    self.speedLabel.text = [NSString stringWithFormat:@"%zd", speed];
-}
-
-- (void)buttonClickAction:(UIButton *)sender {
-    
-    self.isSelected = !self.isSelected;
-    if (self.callback) {
-        self.callback(self, self.isSelected);
-    }
-}
-
-#pragma mark ---- setter
-- (void)setIsSelected:(BOOL)isSelected {
-    
-    _isSelected = isSelected;
-    self.actionButton.selected = isSelected;
-    if (isSelected) {
-        self.titleLabel.text = self.selectTitle;
-    }
-    else {
-        self.titleLabel.text = self.buttonTitle;
-    }
-}
-#pragma mark ----- lazying
-- (UILabel *)titleLabel {
-    
-    if (!_titleLabel) {
-        _titleLabel = [[UILabel alloc] init];
-        _titleLabel.textColor = UIColor.whiteColor;
-        _titleLabel.font = [UIFont systemFontOfSize:12.0f weight:UIFontWeightMedium];
-        _titleLabel.textAlignment = NSTextAlignmentCenter;
-    }
-    return _titleLabel;
-}
-
-- (UILabel *)speedLabel {
-    if (!_speedLabel) {
-        _speedLabel = [[UILabel alloc] init];
-        [_speedLabel setFont:[UIFont systemFontOfSize:10.0f]];
-        _speedLabel.textColor = THEMECOLOR;
-        _speedLabel.textAlignment = NSTextAlignmentCenter;
-    }
-    return _speedLabel;
-}
-
-/*
-// Only override drawRect: if you perform custom drawing.
-// An empty implementation adversely affects performance during animation.
-- (void)drawRect:(CGRect)rect {
-    // Drawing code
-}
-*/
-
-@end

+ 0 - 20
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/StaffView/ScoreAnimationView.h

@@ -1,20 +0,0 @@
-//
-//  ScoreAnimationView.h
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/10.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface ScoreAnimationView : UIView
-
-- (instancetype)initWithFrame:(CGRect)frame animitionDistance:(CGFloat)distance score:(NSInteger)score titleColor:(UIColor *)titleColor imageName:(NSString *)imageName;
-
-- (void)showInView:(UIView *)displayView;
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 76
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/StaffView/ScoreAnimationView.m

@@ -1,76 +0,0 @@
-//
-//  ScoreAnimationView.m
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/10.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import "ScoreAnimationView.h"
-
-@interface ScoreAnimationView ()
-
-@property (nonatomic, assign) CGFloat distanceY;
-
-@property (nonatomic, assign) NSInteger score;
-
-@property (nonatomic, strong) UIColor *scoreColor;
-
-@property (nonatomic, strong) NSString *imgName;
-
-@end
-
-@implementation ScoreAnimationView
-
-
-- (instancetype)initWithFrame:(CGRect)frame animitionDistance:(CGFloat)distance score:(NSInteger)score titleColor:(UIColor *)titleColor imageName:(NSString *)imageName {
-    self = [super initWithFrame:frame];
-    if (self) {
-        self.distanceY = distance;
-        self.score = score;
-        self.scoreColor = titleColor;
-        self.imgName = imageName;
-        [self configView];
-    }
-    return self;
-}
-
-
-- (void)configView {
-    UIImage *image = [UIImage imageNamed:self.imgName];
-    CGFloat rate = image.size.width / image.size.height;
-    UIImageView *scoreImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, rate * 40, 40)];
-    [scoreImage setImage:image];
-    [self addSubview:scoreImage];
-    UILabel *scoreLabel = [[UILabel alloc] init];
-    scoreLabel.frame = CGRectMake(CGRectGetMaxX(scoreImage.frame), 0, 40, 40);
-    scoreLabel.textAlignment = NSTextAlignmentLeft;
-    [scoreLabel setText:[NSString stringWithFormat:@"%zd",self.score]];
-    [scoreLabel setTextColor:self.scoreColor];
-    [scoreLabel setFont:[UIFont systemFontOfSize:18.0f weight:UIFontWeightBold]];
-    [self addSubview:scoreLabel];
-    
-}
-
-- (void)showInView:(UIView *)displayView {
-    [displayView addSubview:self];
-    
-    [UIView animateWithDuration:0.5f animations:^{
-        CGRect frame = self.frame;
-        frame.origin.y -= (self.distanceY + frame.size.height);
-        self.frame = frame;
-    } completion:^(BOOL finished) {
-        [self removeFromSuperview];
-    }];
-}
-
-
-/*
-// Only override drawRect: if you perform custom drawing.
-// An empty implementation adversely affects performance during animation.
-- (void)drawRect:(CGRect)rect {
-    // Drawing code
-}
-*/
-
-@end

+ 0 - 51
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/StaffView/StaffImageDisplayView.h

@@ -1,51 +0,0 @@
-//
-//  StaffImageDisplayView.h
-//  MidiPlayer
-//
-//  Created by Kyle on 2021/12/2.
-//
-
-#import <UIKit/UIKit.h>
-
-
-@interface KSMeasureLocationModel : NSObject
-
-@property (nonatomic, assign) CGFloat positionX;
-
-@property (nonatomic, assign) CGFloat positionY;
-
-@property (nonatomic, assign) CGFloat measureWidth;
-
-@property (nonatomic, assign) CGFloat measureHeight;
-
-@property (nonatomic, assign) NSInteger pageIndex;  // 当前page
-
-@property (nonatomic, strong) UIColor * _Nonnull fillColor; // 填充颜色
-
-@end
-
-NS_ASSUME_NONNULL_BEGIN
-
-
-
-typedef void(^TapCallback)(CGFloat positionX, CGFloat positionY, NSInteger pageIndex);
-
-@interface StaffImageDisplayView : UIView
-
-@property (nonatomic, assign) NSInteger pageIndex;  // 当前page
-
-@property (nonatomic, strong) NSString *imageName;  // 图片名称
-
-- (instancetype)initWithImage:(NSString *)imageName pageIndex:(NSInteger)pageIndex frame:(CGRect)viewFrame;
-
-- (void)viewTapActionCallback:(TapCallback)callback;
-
-- (void)clearAllColorView;
-
-- (void)addColorView:(KSMeasureLocationModel *)model;
-
-- (void)drawColorView:(NSMutableArray *)viewLocatonArray;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 109
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/StaffView/StaffImageDisplayView.m

@@ -1,109 +0,0 @@
-//
-//  StaffImageDisplayView.m
-//  MidiPlayer
-//
-//  Created by Kyle on 2021/12/2.
-//
-
-#import "StaffImageDisplayView.h"
-
-@interface KSColorView : UIView
-
-@end
-
-@implementation KSColorView
-
-
-@end
-
-
-@implementation KSMeasureLocationModel
-
-@end
-
-
-@interface StaffImageDisplayView ()
-
-@property (nonatomic, strong) UIView *bgView;
-
-@property (nonatomic, strong) UIImageView *imageView;
-
-@property (nonatomic, copy) TapCallback callback;
-
-@end
-
-@implementation StaffImageDisplayView
-
-- (instancetype)initWithImage:(NSString *)imageName pageIndex:(NSInteger)pageIndex frame:(CGRect)viewFrame {
-    if (self = [super initWithFrame:viewFrame]) {
-        self.bgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, viewFrame.size.width, viewFrame.size.height)];
-        self.bgView.backgroundColor = [UIColor clearColor];
-        [self addSubview:self.bgView];
-        
-        self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, viewFrame.size.width, viewFrame.size.height)];
-        self.imageView.userInteractionEnabled = YES;
-        [self addSubview:self.imageView];
-        
-        self.imageName = imageName;
-        self.pageIndex = pageIndex;
-    }
-    return self;
-}
-
-
-- (void)viewTapActionCallback:(TapCallback)callback {
-    if (callback) {
-        self.callback = callback;
-    }
-}
-
-- (void)clearAllColorView {
-    for (UIView *view in self.bgView.subviews) {
-        if ([view isKindOfClass:[KSColorView class]]) {
-            [view removeFromSuperview];
-        }
-    }
-}
-
-- (void)addColorView:(KSMeasureLocationModel *)model {
-    
-    KSColorView *colorView = [[KSColorView alloc] initWithFrame:CGRectMake(model.positionX, model.positionY, model.measureWidth, model.measureHeight)];
-    colorView.backgroundColor = model.fillColor;
-    [self.bgView addSubview:colorView];
-}
-
-- (void)drawColorView:(NSMutableArray *)viewLocatonArray {
-    for (KSMeasureLocationModel *model in viewLocatonArray) {
-        KSColorView *colorView = [[KSColorView alloc] initWithFrame:CGRectMake(model.positionX, model.positionY, model.measureWidth, model.measureHeight)];
-        colorView.backgroundColor = model.fillColor;
-        [self.bgView addSubview:colorView];
-    }
-}
-
-#pragma mark ------- setting
-- (void)setImageName:(NSString *)imageName {
-    _imageName = imageName;
-    [self.imageView setImage:[UIImage imageNamed:imageName]];
-}
-
-- (void)setPageIndex:(NSInteger)pageIndex {
-    _pageIndex = pageIndex;
-}
-
-- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
-    UITouch *touch = [touches anyObject];
-    CGPoint point = [touch locationInView:self];
-    if (self.callback) {
-        self.callback(point.x, point.y, self.pageIndex);
-    }
-}
-
-/*
-// Only override drawRect: if you perform custom drawing.
-// An empty implementation adversely affects performance during animation.
-- (void)drawRect:(CGRect)rect {
-    // Drawing code
-}
-*/
-
-@end

+ 0 - 39
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/TipsAlert/EvaluateResultAlert.h

@@ -1,39 +0,0 @@
-//
-//  EvaluateResultAlert.h
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/10.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-typedef NS_ENUM(NSInteger, EVALUATE_RESULT_ACTION) {
-    EVALUATE_RESULT_ACTION_CANCLE,  // 取消
-    EVALUATE_RESULT_ACTION_SUBMIT, // 上传到云端
-    EVALUATE_RESULT_ACTION_SHARE,  // 分享
-    EVALUATE_RESULT_ACTION_PRACTICE, // 练习
-    EVALUATE_RESULT_ACTION_TAYAGAIN, // 再试一次
-    EVALUATE_RESULT_ACTION_REPORT,   // 查看报告
-};
-
-typedef void(^EvaluateResultCallback)(EVALUATE_RESULT_ACTION action);
-
-@interface EvaluateResultAlert : UIView
-
-+ (instancetype)shareInstance;
-
-/// 配置页面显示
-/// @param score 分数
-/// @param intonation 音准
-/// @param cadence 节奏
-/// @param integrity 完整度
-- (void)configWithScore:(NSInteger)score intonation:(NSInteger)intonation cadence:(NSInteger)cadence integrity:(NSInteger)integrity;
-
-- (void)resultCallback:(EvaluateResultCallback)callback;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 144
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/TipsAlert/EvaluateResultAlert.m

@@ -1,144 +0,0 @@
-//
-//  EvaluateResultAlert.m
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/10.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import "EvaluateResultAlert.h"
-
-@interface EvaluateResultAlert ()
-
-@property (weak, nonatomic) IBOutlet UILabel *scoreLabel;
-
-@property (weak, nonatomic) IBOutlet UILabel *scoreDesc;
-// 音准
-@property (weak, nonatomic) IBOutlet UIView *intonationView;
-@property (weak, nonatomic) IBOutlet UILabel *intonationScore;
-@property (weak, nonatomic) IBOutlet UIView *intonationValueView;
-@property (weak, nonatomic) IBOutlet NSLayoutConstraint *intonationWidth;
-
-// 节奏
-@property (weak, nonatomic) IBOutlet UIView *rhythmView;
-@property (weak, nonatomic) IBOutlet UILabel *rhythmLabel;
-@property (weak, nonatomic) IBOutlet UIView *rhyhtmVauleView;
-@property (weak, nonatomic) IBOutlet NSLayoutConstraint *rhythmWidth;
-
-// 完整性
-@property (weak, nonatomic) IBOutlet UIView *integrityView;
-@property (weak, nonatomic) IBOutlet UILabel *integrityLabel;
-@property (weak, nonatomic) IBOutlet UIView *integrityValueView;
-@property (weak, nonatomic) IBOutlet NSLayoutConstraint *integrityWidth;
-
-
-@property (weak, nonatomic) IBOutlet UILabel *reportDesc;
-
-@property (weak, nonatomic) IBOutlet UIView *lineView;
-
-@property (nonatomic, copy) EvaluateResultCallback callback;
-
-@property (nonatomic, assign) NSInteger score;
-
-@property (nonatomic, assign) NSInteger intonation;
-
-@property (nonatomic, assign) NSInteger cadence;
-
-@property (nonatomic, assign) NSInteger integrity;
-@end
-
-@implementation EvaluateResultAlert
-
-+ (instancetype)shareInstance {
-    EvaluateResultAlert *view = [[[NSBundle mainBundle] loadNibNamed:@"EvaluateResultAlert" owner:nil options:nil] firstObject];
-    return view;
-}
-
-- (void)configWithScore:(NSInteger)score intonation:(NSInteger)intonation cadence:(NSInteger)cadence integrity:(NSInteger)integrity {
-    self.score = score;
-    self.intonation = intonation;
-    self.cadence = cadence;
-    self.integrity = integrity;
-}
-
-- (void)setScore:(NSInteger)score {
-    _score = score;
-    NSString *desc = @"";
-    NSString *reportMessage = @"";
-    if (score > 80) {
-        desc = @"你很棒";
-        reportMessage = @"你的演奏非常不错,音准的把握和节奏稍有瑕疵,完整性把握的很好~";
-    }
-    else if (score > 60) {
-        desc = @"展露头角";
-        reportMessage = @"你的演奏还不错,继续加油吧,加强音准,离完美就差一步啦~";
-    }
-    else if (score > 40) {
-        desc = @"突破自我";
-        reportMessage = @"你的演奏还不流畅,音准和节奏还需加强,科学的练习才能更完美哦~";
-    }
-    else if (score > 20) {
-        desc = @"还要加油哦~";
-        reportMessage = @"你的演奏还不熟练,音准和完整性还需加强,加紧训练才能有好成绩哦~";
-    }
-    else {
-        desc = @"敢于尝试";
-        reportMessage = @"你的演奏不太好,音准和完整性还需加强,再练一练吧~";
-    }
-    self.scoreLabel.text = [NSString stringWithFormat:@"%zd",score];
-    self.scoreDesc.text = desc;
-
-    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
-    [paragraphStyle setLineSpacing:4];//调整行间距
-    NSMutableAttributedString *attrs = [[NSMutableAttributedString alloc] initWithString:reportMessage attributes:@{NSParagraphStyleAttributeName:paragraphStyle,NSFontAttributeName:[UIFont systemFontOfSize:14.0f],NSForegroundColorAttributeName:HexRGB(0x808080)}];
-    self.reportDesc.attributedText = attrs;
-    
-}
-
-- (void)setIntonation:(NSInteger)intonation {
-    _intonation = intonation;
-    self.intonationScore.text = [NSString stringWithFormat:@"%zd",intonation];
-    [UIView animateWithDuration:0.3f animations:^{
-        self.integrityWidth.constant = 180 * (intonation/100.0f);
-    }];
-}
-
-- (void)setCadence:(NSInteger)cadence {
-    _cadence = cadence;
-    self.rhythmLabel.text = [NSString stringWithFormat:@"%zd",cadence];
-    [UIView animateWithDuration:0.3f animations:^{
-        self.rhythmWidth.constant = 180 * (cadence/100.0f);
-    }];
-}
-
-- (void)setIntegrity:(NSInteger)integrity {
-    _integrity = integrity;
-    self.integrityLabel.text = [NSString stringWithFormat:@"%zd",integrity];
-    [UIView animateWithDuration:0.3f animations:^{
-        self.integrityWidth.constant = 180 * (integrity/100.0f);
-    }];
-}
-
-- (void)resultCallback:(EvaluateResultCallback)callback {
-    if (callback) {
-        self.callback = callback;
-    }
-}
-
-- (IBAction)buttonClickAction:(UIButton *)sender {
-    NSInteger index = sender.tag - 1000;
-    if (self.callback) {
-        self.callback(index);
-    }
-}
-
-
-/*
-// Only override drawRect: if you perform custom drawing.
-// An empty implementation adversely affects performance during animation.
-- (void)drawRect:(CGRect)rect {
-    // Drawing code
-}
-*/
-
-@end

+ 0 - 391
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/TipsAlert/EvaluateResultAlert.xib

@@ -1,391 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
-    <device id="retina6_1" orientation="portrait" appearance="light"/>
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
-        <capability name="System colors in document resources" minToolsVersion="11.0"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <objects>
-        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
-        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="EvaluateResultAlert">
-            <rect key="frame" x="0.0" y="0.0" width="736" height="454"/>
-            <autoresizingMask key="autoresizingMask"/>
-            <subviews>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kev-3r-AV2">
-                    <rect key="frame" x="95.5" y="24" width="545" height="415"/>
-                    <subviews>
-                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="9ti-sU-Ve9">
-                            <rect key="frame" x="181.5" y="0.0" width="363.5" height="415"/>
-                            <subviews>
-                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qHz-48-PaW">
-                                    <rect key="frame" x="18" y="26" width="4" height="18"/>
-                                    <color key="backgroundColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="calibratedRGB"/>
-                                    <constraints>
-                                        <constraint firstAttribute="height" constant="18" id="DqZ-My-Ord"/>
-                                        <constraint firstAttribute="width" constant="4" id="hi7-S1-jpO"/>
-                                    </constraints>
-                                    <userDefinedRuntimeAttributes>
-                                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                            <real key="value" value="2"/>
-                                        </userDefinedRuntimeAttribute>
-                                    </userDefinedRuntimeAttributes>
-                                </view>
-                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="智能评分" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="anF-LP-hlF">
-                                    <rect key="frame" x="30" y="24" width="74" height="22"/>
-                                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="18"/>
-                                    <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
-                                    <nil key="highlightedColor"/>
-                                </label>
-                                <button opaque="NO" tag="1001" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FA5-n2-FUc">
-                                    <rect key="frame" x="189.5" y="21" width="86" height="28"/>
-                                    <color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.93725490196078431" alpha="1" colorSpace="calibratedRGB"/>
-                                    <constraints>
-                                        <constraint firstAttribute="width" constant="86" id="Cww-TE-rnF"/>
-                                        <constraint firstAttribute="height" constant="28" id="fYt-SX-XQi"/>
-                                    </constraints>
-                                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
-                                    <state key="normal" title="上传到云端">
-                                        <color key="titleColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="calibratedRGB"/>
-                                    </state>
-                                    <userDefinedRuntimeAttributes>
-                                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                            <real key="value" value="14"/>
-                                        </userDefinedRuntimeAttribute>
-                                    </userDefinedRuntimeAttributes>
-                                    <connections>
-                                        <action selector="buttonClickAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="r6c-Zo-YwX"/>
-                                    </connections>
-                                </button>
-                                <button opaque="NO" tag="1002" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aFf-78-FUB">
-                                    <rect key="frame" x="283.5" y="21" width="66" height="28"/>
-                                    <color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.93725490196078431" alpha="1" colorSpace="calibratedRGB"/>
-                                    <constraints>
-                                        <constraint firstAttribute="height" constant="28" id="0kj-eU-0Lb"/>
-                                        <constraint firstAttribute="width" constant="66" id="bN8-Zz-1EC"/>
-                                    </constraints>
-                                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
-                                    <state key="normal" title="分享">
-                                        <color key="titleColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="calibratedRGB"/>
-                                    </state>
-                                    <userDefinedRuntimeAttributes>
-                                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                            <real key="value" value="14"/>
-                                        </userDefinedRuntimeAttribute>
-                                    </userDefinedRuntimeAttributes>
-                                    <connections>
-                                        <action selector="buttonClickAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="oxR-3W-4P3"/>
-                                    </connections>
-                                </button>
-                                <button opaque="NO" tag="1003" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="N9k-Lb-OD5">
-                                    <rect key="frame" x="18" y="361" width="103" height="34"/>
-                                    <color key="backgroundColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="calibratedRGB"/>
-                                    <constraints>
-                                        <constraint firstAttribute="height" constant="34" id="EAa-IF-fgH"/>
-                                    </constraints>
-                                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
-                                    <state key="normal" title="去练习"/>
-                                    <userDefinedRuntimeAttributes>
-                                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                            <real key="value" value="17"/>
-                                        </userDefinedRuntimeAttribute>
-                                    </userDefinedRuntimeAttributes>
-                                    <connections>
-                                        <action selector="buttonClickAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="sYQ-1S-l5u"/>
-                                    </connections>
-                                </button>
-                                <button opaque="NO" tag="1004" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qqs-xN-SGQ">
-                                    <rect key="frame" x="127" y="361" width="102.5" height="34"/>
-                                    <color key="backgroundColor" red="0.96862745098039216" green="0.57647058823529407" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
-                                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
-                                    <state key="normal" title="再试一次"/>
-                                    <userDefinedRuntimeAttributes>
-                                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                            <real key="value" value="17"/>
-                                        </userDefinedRuntimeAttribute>
-                                    </userDefinedRuntimeAttributes>
-                                    <connections>
-                                        <action selector="buttonClickAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="ufF-E1-csh"/>
-                                    </connections>
-                                </button>
-                                <button opaque="NO" tag="1005" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="EOy-Rm-p6b">
-                                    <rect key="frame" x="235.5" y="361" width="103" height="34"/>
-                                    <color key="backgroundColor" red="0.96862745098039216" green="0.70980392156862748" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
-                                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
-                                    <state key="normal" title="查看报告"/>
-                                    <userDefinedRuntimeAttributes>
-                                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                            <real key="value" value="17"/>
-                                        </userDefinedRuntimeAttribute>
-                                    </userDefinedRuntimeAttributes>
-                                    <connections>
-                                        <action selector="buttonClickAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="Tgi-ZH-3lq"/>
-                                    </connections>
-                                </button>
-                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="B2m-Gc-bZ4">
-                                    <rect key="frame" x="22" y="342" width="316.5" height="1"/>
-                                    <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                                    <constraints>
-                                        <constraint firstAttribute="height" constant="1" id="jbf-7j-0Js"/>
-                                    </constraints>
-                                </view>
-                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="音准" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="u9l-uA-IVQ">
-                                    <rect key="frame" x="24" y="86" width="42" height="17"/>
-                                    <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="13"/>
-                                    <color key="textColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="calibratedRGB"/>
-                                    <nil key="highlightedColor"/>
-                                </label>
-                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lV9-fw-Fkw">
-                                    <rect key="frame" x="76" y="84" width="180" height="21"/>
-                                    <subviews>
-                                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="d2B-ck-SlX">
-                                            <rect key="frame" x="0.0" y="0.0" width="0.0" height="21"/>
-                                            <color key="backgroundColor" red="0.0039215686274509803" green="0.75686274509803919" blue="0.70980392156862748" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
-                                            <constraints>
-                                                <constraint firstAttribute="width" id="qbr-4x-9un"/>
-                                            </constraints>
-                                        </view>
-                                    </subviews>
-                                    <color key="backgroundColor" red="0.96078431372549022" green="0.95686274509803915" blue="0.94901960784313721" alpha="1" colorSpace="calibratedRGB"/>
-                                    <constraints>
-                                        <constraint firstItem="d2B-ck-SlX" firstAttribute="top" secondItem="lV9-fw-Fkw" secondAttribute="top" id="bDK-RK-k7r"/>
-                                        <constraint firstAttribute="height" constant="21" id="pQa-YV-oev"/>
-                                        <constraint firstItem="d2B-ck-SlX" firstAttribute="leading" secondItem="lV9-fw-Fkw" secondAttribute="leading" id="r2k-1S-L8y"/>
-                                        <constraint firstAttribute="width" constant="180" id="w7S-UX-ntU"/>
-                                        <constraint firstAttribute="bottom" secondItem="d2B-ck-SlX" secondAttribute="bottom" id="wvz-Vs-JQV"/>
-                                    </constraints>
-                                </view>
-                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bCl-zp-NUb">
-                                    <rect key="frame" x="266" y="94.5" width="0.0" height="0.0"/>
-                                    <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/>
-                                    <color key="textColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="calibratedRGB"/>
-                                    <nil key="highlightedColor"/>
-                                </label>
-                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="节奏" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Tzk-7k-87s">
-                                    <rect key="frame" x="24" y="131" width="42" height="17"/>
-                                    <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="13"/>
-                                    <color key="textColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="calibratedRGB"/>
-                                    <nil key="highlightedColor"/>
-                                </label>
-                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aJS-TL-5oc">
-                                    <rect key="frame" x="76" y="129" width="180" height="21"/>
-                                    <subviews>
-                                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="zV2-Tw-oe3">
-                                            <rect key="frame" x="0.0" y="0.0" width="0.0" height="21"/>
-                                            <color key="backgroundColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
-                                            <constraints>
-                                                <constraint firstAttribute="width" id="bs0-i5-6c0"/>
-                                            </constraints>
-                                        </view>
-                                    </subviews>
-                                    <color key="backgroundColor" red="0.96078431369999995" green="0.95686274510000002" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
-                                    <constraints>
-                                        <constraint firstAttribute="bottom" secondItem="zV2-Tw-oe3" secondAttribute="bottom" id="7oR-mW-2GT"/>
-                                        <constraint firstItem="zV2-Tw-oe3" firstAttribute="top" secondItem="aJS-TL-5oc" secondAttribute="top" id="KC3-D9-GxU"/>
-                                        <constraint firstItem="zV2-Tw-oe3" firstAttribute="leading" secondItem="aJS-TL-5oc" secondAttribute="leading" id="fUK-ez-Zmq"/>
-                                    </constraints>
-                                </view>
-                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0PX-DQ-geK">
-                                    <rect key="frame" x="266" y="139.5" width="0.0" height="0.0"/>
-                                    <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/>
-                                    <color key="textColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="calibratedRGB"/>
-                                    <nil key="highlightedColor"/>
-                                </label>
-                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="完整性" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="J7e-ik-yVX">
-                                    <rect key="frame" x="24" y="176" width="42" height="17"/>
-                                    <constraints>
-                                        <constraint firstAttribute="height" constant="17" id="ME6-xN-Kf8"/>
-                                        <constraint firstAttribute="width" constant="42" id="kzu-60-diG"/>
-                                    </constraints>
-                                    <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="13"/>
-                                    <color key="textColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="calibratedRGB"/>
-                                    <nil key="highlightedColor"/>
-                                </label>
-                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qd3-W6-ODw">
-                                    <rect key="frame" x="76" y="174" width="180" height="21"/>
-                                    <subviews>
-                                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aU3-L4-zQd">
-                                            <rect key="frame" x="0.0" y="0.0" width="0.0" height="21"/>
-                                            <color key="backgroundColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
-                                            <constraints>
-                                                <constraint firstAttribute="width" id="adA-kZ-k6W"/>
-                                            </constraints>
-                                        </view>
-                                    </subviews>
-                                    <color key="backgroundColor" red="0.96078431369999995" green="0.95686274510000002" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
-                                    <constraints>
-                                        <constraint firstAttribute="bottom" secondItem="aU3-L4-zQd" secondAttribute="bottom" id="fGq-9o-0er"/>
-                                        <constraint firstItem="aU3-L4-zQd" firstAttribute="leading" secondItem="qd3-W6-ODw" secondAttribute="leading" id="rz6-bU-tJv"/>
-                                        <constraint firstItem="aU3-L4-zQd" firstAttribute="top" secondItem="qd3-W6-ODw" secondAttribute="top" id="yYd-cO-9jL"/>
-                                    </constraints>
-                                </view>
-                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kw3-ma-jdO">
-                                    <rect key="frame" x="266" y="184.5" width="0.0" height="0.0"/>
-                                    <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/>
-                                    <color key="textColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="calibratedRGB"/>
-                                    <nil key="highlightedColor"/>
-                                </label>
-                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZnY-N0-3Om">
-                                    <rect key="frame" x="24" y="322" width="321.5" height="0.0"/>
-                                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                                    <color key="textColor" red="0.50196078431372548" green="0.50196078431372548" blue="0.50196078431372548" alpha="1" colorSpace="calibratedRGB"/>
-                                    <nil key="highlightedColor"/>
-                                </label>
-                            </subviews>
-                            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                            <constraints>
-                                <constraint firstAttribute="trailing" secondItem="B2m-Gc-bZ4" secondAttribute="trailing" constant="25" id="0Ll-BW-cOb"/>
-                                <constraint firstItem="qqs-xN-SGQ" firstAttribute="width" secondItem="N9k-Lb-OD5" secondAttribute="width" id="0y5-Py-7qm"/>
-                                <constraint firstItem="aJS-TL-5oc" firstAttribute="height" secondItem="lV9-fw-Fkw" secondAttribute="height" id="1PQ-1o-fyY"/>
-                                <constraint firstItem="bCl-zp-NUb" firstAttribute="centerY" secondItem="u9l-uA-IVQ" secondAttribute="centerY" id="1mK-3w-dID"/>
-                                <constraint firstAttribute="trailing" secondItem="EOy-Rm-p6b" secondAttribute="trailing" constant="25" id="4FH-Df-3rl"/>
-                                <constraint firstItem="qqs-xN-SGQ" firstAttribute="height" secondItem="N9k-Lb-OD5" secondAttribute="height" id="5x1-sv-917"/>
-                                <constraint firstItem="qqs-xN-SGQ" firstAttribute="leading" secondItem="N9k-Lb-OD5" secondAttribute="trailing" constant="6" id="6xs-va-Kpg"/>
-                                <constraint firstItem="0PX-DQ-geK" firstAttribute="centerY" secondItem="Tzk-7k-87s" secondAttribute="centerY" id="9Ty-3v-Seg"/>
-                                <constraint firstItem="EOy-Rm-p6b" firstAttribute="leading" secondItem="qqs-xN-SGQ" secondAttribute="trailing" constant="6" id="AnC-5O-ZOv"/>
-                                <constraint firstItem="qHz-48-PaW" firstAttribute="top" secondItem="9ti-sU-Ve9" secondAttribute="top" constant="26" id="Bf4-ai-1BP"/>
-                                <constraint firstItem="qd3-W6-ODw" firstAttribute="leading" secondItem="lV9-fw-Fkw" secondAttribute="leading" id="D2p-Pj-34t"/>
-                                <constraint firstItem="aFf-78-FUB" firstAttribute="centerY" secondItem="anF-LP-hlF" secondAttribute="centerY" id="FCK-yo-Kp9"/>
-                                <constraint firstItem="Tzk-7k-87s" firstAttribute="top" secondItem="u9l-uA-IVQ" secondAttribute="bottom" constant="28" id="H7y-ps-gWy"/>
-                                <constraint firstItem="aFf-78-FUB" firstAttribute="leading" secondItem="FA5-n2-FUc" secondAttribute="trailing" constant="8" id="HUZ-wT-Le6"/>
-                                <constraint firstItem="aJS-TL-5oc" firstAttribute="width" secondItem="lV9-fw-Fkw" secondAttribute="width" id="HhG-Df-wZ4"/>
-                                <constraint firstItem="aJS-TL-5oc" firstAttribute="leading" secondItem="lV9-fw-Fkw" secondAttribute="leading" id="JaX-3z-5Ii"/>
-                                <constraint firstItem="kw3-ma-jdO" firstAttribute="centerY" secondItem="J7e-ik-yVX" secondAttribute="centerY" id="Jsv-0c-3NB"/>
-                                <constraint firstItem="lV9-fw-Fkw" firstAttribute="leading" secondItem="u9l-uA-IVQ" secondAttribute="trailing" constant="10" id="MY4-pt-KZB"/>
-                                <constraint firstItem="N9k-Lb-OD5" firstAttribute="top" secondItem="B2m-Gc-bZ4" secondAttribute="bottom" constant="18" id="MvV-Yg-H1P"/>
-                                <constraint firstItem="qqs-xN-SGQ" firstAttribute="bottom" secondItem="N9k-Lb-OD5" secondAttribute="bottom" id="NgX-Kg-1IT"/>
-                                <constraint firstAttribute="bottom" secondItem="N9k-Lb-OD5" secondAttribute="bottom" constant="20" id="P4h-rt-go9"/>
-                                <constraint firstItem="kw3-ma-jdO" firstAttribute="leading" secondItem="bCl-zp-NUb" secondAttribute="leading" id="Qwk-k1-LwN"/>
-                                <constraint firstItem="Tzk-7k-87s" firstAttribute="height" secondItem="u9l-uA-IVQ" secondAttribute="height" id="StV-Ao-1YB"/>
-                                <constraint firstItem="Tzk-7k-87s" firstAttribute="trailing" secondItem="u9l-uA-IVQ" secondAttribute="trailing" id="Tjh-Ib-jqQ"/>
-                                <constraint firstAttribute="trailing" secondItem="ZnY-N0-3Om" secondAttribute="trailing" constant="18" id="TsD-QX-8Vh"/>
-                                <constraint firstItem="J7e-ik-yVX" firstAttribute="top" secondItem="Tzk-7k-87s" secondAttribute="bottom" constant="28" id="V46-Hp-dso"/>
-                                <constraint firstItem="Tzk-7k-87s" firstAttribute="width" secondItem="u9l-uA-IVQ" secondAttribute="width" id="Vem-uQ-w6K"/>
-                                <constraint firstItem="J7e-ik-yVX" firstAttribute="trailing" secondItem="u9l-uA-IVQ" secondAttribute="trailing" id="YCn-51-m0o"/>
-                                <constraint firstItem="N9k-Lb-OD5" firstAttribute="leading" secondItem="9ti-sU-Ve9" secondAttribute="leading" constant="18" id="Ygk-CA-dmb"/>
-                                <constraint firstItem="anF-LP-hlF" firstAttribute="leading" secondItem="qHz-48-PaW" secondAttribute="trailing" constant="8" id="ZWk-LI-a0b"/>
-                                <constraint firstItem="bCl-zp-NUb" firstAttribute="leading" secondItem="lV9-fw-Fkw" secondAttribute="trailing" constant="10" id="a9o-Fa-wbA"/>
-                                <constraint firstItem="0PX-DQ-geK" firstAttribute="leading" secondItem="bCl-zp-NUb" secondAttribute="leading" id="aaD-pL-Tdx"/>
-                                <constraint firstItem="EOy-Rm-p6b" firstAttribute="width" secondItem="N9k-Lb-OD5" secondAttribute="width" id="b6b-G0-aw3"/>
-                                <constraint firstItem="EOy-Rm-p6b" firstAttribute="bottom" secondItem="N9k-Lb-OD5" secondAttribute="bottom" id="cew-ZA-UoY"/>
-                                <constraint firstItem="J7e-ik-yVX" firstAttribute="height" secondItem="u9l-uA-IVQ" secondAttribute="height" id="dUV-3d-78J"/>
-                                <constraint firstItem="qd3-W6-ODw" firstAttribute="height" secondItem="lV9-fw-Fkw" secondAttribute="height" id="dXq-wT-uiN"/>
-                                <constraint firstItem="u9l-uA-IVQ" firstAttribute="top" secondItem="anF-LP-hlF" secondAttribute="bottom" constant="40" id="eBH-Kl-b0w"/>
-                                <constraint firstItem="qd3-W6-ODw" firstAttribute="centerY" secondItem="J7e-ik-yVX" secondAttribute="centerY" id="fZs-U9-5oF"/>
-                                <constraint firstItem="B2m-Gc-bZ4" firstAttribute="top" secondItem="ZnY-N0-3Om" secondAttribute="bottom" constant="20" id="hee-RI-XsM"/>
-                                <constraint firstItem="qd3-W6-ODw" firstAttribute="width" secondItem="lV9-fw-Fkw" secondAttribute="width" id="ifa-aV-FqI"/>
-                                <constraint firstAttribute="trailing" secondItem="aFf-78-FUB" secondAttribute="trailing" constant="14" id="k3w-ZR-Clf"/>
-                                <constraint firstItem="anF-LP-hlF" firstAttribute="centerY" secondItem="qHz-48-PaW" secondAttribute="centerY" id="kY3-jz-wOn"/>
-                                <constraint firstItem="J7e-ik-yVX" firstAttribute="width" secondItem="u9l-uA-IVQ" secondAttribute="width" id="lnf-vz-BTx"/>
-                                <constraint firstItem="FA5-n2-FUc" firstAttribute="centerY" secondItem="anF-LP-hlF" secondAttribute="centerY" id="n3R-a3-rrN"/>
-                                <constraint firstItem="EOy-Rm-p6b" firstAttribute="height" secondItem="N9k-Lb-OD5" secondAttribute="height" id="nRz-Ve-yEn"/>
-                                <constraint firstItem="aJS-TL-5oc" firstAttribute="centerY" secondItem="Tzk-7k-87s" secondAttribute="centerY" id="o2E-z3-pga"/>
-                                <constraint firstItem="B2m-Gc-bZ4" firstAttribute="leading" secondItem="9ti-sU-Ve9" secondAttribute="leading" constant="22" id="qfD-HZ-Ru4"/>
-                                <constraint firstItem="lV9-fw-Fkw" firstAttribute="centerY" secondItem="u9l-uA-IVQ" secondAttribute="centerY" id="r6X-cJ-CxD"/>
-                                <constraint firstItem="J7e-ik-yVX" firstAttribute="leading" secondItem="9ti-sU-Ve9" secondAttribute="leading" constant="24" id="rj2-MB-Xkx"/>
-                                <constraint firstItem="ZnY-N0-3Om" firstAttribute="leading" secondItem="9ti-sU-Ve9" secondAttribute="leading" constant="24" id="vVX-Um-Wsa"/>
-                                <constraint firstItem="qHz-48-PaW" firstAttribute="leading" secondItem="9ti-sU-Ve9" secondAttribute="leading" constant="18" id="yQQ-hp-WN0"/>
-                            </constraints>
-                        </view>
-                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="evaluate_logo" translatesAutoresizingMaskIntoConstraints="NO" id="clo-Lu-5re">
-                            <rect key="frame" x="14" y="62" width="145.5" height="143.5"/>
-                            <constraints>
-                                <constraint firstAttribute="width" secondItem="clo-Lu-5re" secondAttribute="height" multiplier="145:143" id="R5I-oV-F9j"/>
-                            </constraints>
-                        </imageView>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fjf-Cx-HBS">
-                            <rect key="frame" x="75" y="215.5" width="0.0" height="0.0"/>
-                            <fontDescription key="fontDescription" type="boldSystem" pointSize="38"/>
-                            <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qbk-ED-W1i">
-                            <rect key="frame" x="87" y="215.5" width="0.0" height="0.0"/>
-                            <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="23"/>
-                            <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="分" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9eP-w3-Oz4">
-                            <rect key="frame" x="75" y="180.5" width="24" height="28"/>
-                            <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="23"/>
-                            <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                    </subviews>
-                    <color key="backgroundColor" red="0.0039215686274509803" green="0.75686274509803919" blue="0.70980392156862748" alpha="1" colorSpace="calibratedRGB"/>
-                    <constraints>
-                        <constraint firstItem="9eP-w3-Oz4" firstAttribute="leading" secondItem="fjf-Cx-HBS" secondAttribute="trailing" id="50u-Cc-Ao9"/>
-                        <constraint firstItem="clo-Lu-5re" firstAttribute="leading" secondItem="kev-3r-AV2" secondAttribute="leading" constant="14" id="9wJ-QD-J4c"/>
-                        <constraint firstAttribute="bottom" secondItem="9ti-sU-Ve9" secondAttribute="bottom" id="Eyh-rc-wKX"/>
-                        <constraint firstItem="clo-Lu-5re" firstAttribute="top" secondItem="kev-3r-AV2" secondAttribute="top" constant="62" id="F5F-QP-1Q4"/>
-                        <constraint firstItem="9ti-sU-Ve9" firstAttribute="leading" secondItem="clo-Lu-5re" secondAttribute="trailing" constant="22" id="HJO-Yz-Sj6"/>
-                        <constraint firstAttribute="width" constant="545" id="PBs-mS-Jsg"/>
-                        <constraint firstItem="9ti-sU-Ve9" firstAttribute="leading" secondItem="kev-3r-AV2" secondAttribute="centerX" multiplier="2/3" id="Pz9-QB-6ac"/>
-                        <constraint firstItem="Qbk-ED-W1i" firstAttribute="centerX" secondItem="clo-Lu-5re" secondAttribute="centerX" id="RSO-m9-77y"/>
-                        <constraint firstItem="fjf-Cx-HBS" firstAttribute="centerX" secondItem="clo-Lu-5re" secondAttribute="centerX" constant="-12" id="VRl-jd-YiN"/>
-                        <constraint firstItem="9eP-w3-Oz4" firstAttribute="bottom" secondItem="fjf-Cx-HBS" secondAttribute="bottom" constant="-7" id="bm0-jX-3Sx"/>
-                        <constraint firstItem="9ti-sU-Ve9" firstAttribute="top" secondItem="kev-3r-AV2" secondAttribute="top" id="h7j-uV-HOs"/>
-                        <constraint firstItem="Qbk-ED-W1i" firstAttribute="top" secondItem="fjf-Cx-HBS" secondAttribute="bottom" id="ioQ-H8-Dhi"/>
-                        <constraint firstAttribute="trailing" secondItem="9ti-sU-Ve9" secondAttribute="trailing" id="jdw-Gv-9To"/>
-                        <constraint firstItem="fjf-Cx-HBS" firstAttribute="top" secondItem="clo-Lu-5re" secondAttribute="bottom" constant="10" id="zL2-rC-Vbr"/>
-                    </constraints>
-                    <userDefinedRuntimeAttributes>
-                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                            <real key="value" value="20"/>
-                        </userDefinedRuntimeAttribute>
-                    </userDefinedRuntimeAttributes>
-                </view>
-                <button opaque="NO" tag="1000" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ECe-lf-Wo6">
-                    <rect key="frame" x="640.5" y="2" width="44" height="44"/>
-                    <constraints>
-                        <constraint firstAttribute="height" constant="44" id="72Y-ys-SLx"/>
-                        <constraint firstAttribute="width" constant="44" id="BEV-8f-Nl5"/>
-                    </constraints>
-                    <state key="normal" image="cloud_cancle"/>
-                    <connections>
-                        <action selector="buttonClickAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="rhv-1p-kya"/>
-                    </connections>
-                </button>
-            </subviews>
-            <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.52000000000000002" colorSpace="custom" customColorSpace="calibratedRGB"/>
-            <constraints>
-                <constraint firstAttribute="bottom" secondItem="kev-3r-AV2" secondAttribute="bottom" constant="15" id="8Zy-2w-zN8"/>
-                <constraint firstItem="ECe-lf-Wo6" firstAttribute="centerY" secondItem="kev-3r-AV2" secondAttribute="top" id="DUE-TX-w7J"/>
-                <constraint firstItem="kev-3r-AV2" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="QaD-fh-unz"/>
-                <constraint firstItem="kev-3r-AV2" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="24" id="hYe-gN-0u7"/>
-                <constraint firstItem="ECe-lf-Wo6" firstAttribute="leading" secondItem="kev-3r-AV2" secondAttribute="trailing" id="tdE-sB-9hR"/>
-            </constraints>
-            <nil key="simulatedTopBarMetrics"/>
-            <nil key="simulatedBottomBarMetrics"/>
-            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
-            <connections>
-                <outlet property="integrityLabel" destination="kw3-ma-jdO" id="7D9-hn-DGT"/>
-                <outlet property="integrityValueView" destination="aU3-L4-zQd" id="qik-rX-eB1"/>
-                <outlet property="integrityView" destination="qd3-W6-ODw" id="boe-4l-XqJ"/>
-                <outlet property="integrityWidth" destination="adA-kZ-k6W" id="tiT-Fe-MM1"/>
-                <outlet property="intonationScore" destination="bCl-zp-NUb" id="erm-vk-XsR"/>
-                <outlet property="intonationValueView" destination="d2B-ck-SlX" id="0Jy-Ok-czQ"/>
-                <outlet property="intonationView" destination="lV9-fw-Fkw" id="fYQ-vK-OgC"/>
-                <outlet property="intonationWidth" destination="qbr-4x-9un" id="59O-c4-FDQ"/>
-                <outlet property="lineView" destination="B2m-Gc-bZ4" id="dWv-E0-YIg"/>
-                <outlet property="reportDesc" destination="ZnY-N0-3Om" id="Mtw-T0-rVh"/>
-                <outlet property="rhyhtmVauleView" destination="zV2-Tw-oe3" id="kEh-Ed-MHt"/>
-                <outlet property="rhythmLabel" destination="0PX-DQ-geK" id="b3m-fm-MtQ"/>
-                <outlet property="rhythmView" destination="aJS-TL-5oc" id="7dF-52-tZH"/>
-                <outlet property="rhythmWidth" destination="bs0-i5-6c0" id="2MX-1r-sJX"/>
-                <outlet property="scoreDesc" destination="Qbk-ED-W1i" id="BUa-zv-opz"/>
-                <outlet property="scoreLabel" destination="fjf-Cx-HBS" id="cyy-jn-IRU"/>
-            </connections>
-            <point key="canvasLocation" x="-49.275362318840585" y="-4.0178571428571423"/>
-        </view>
-    </objects>
-    <resources>
-        <image name="cloud_cancle" width="26" height="26"/>
-        <image name="evaluate_logo" width="166" height="143"/>
-        <systemColor name="systemBackgroundColor">
-            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-        </systemColor>
-    </resources>
-</document>

+ 0 - 22
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/TipsAlert/NoWiredTipsAlert.h

@@ -1,22 +0,0 @@
-//
-//  NoWiredTipsAlert.h
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/12.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-NS_ASSUME_NONNULL_BEGIN
-typedef void(^CheckWiredCallback)(void);
-
-@interface NoWiredTipsAlert : UIView
-
-+ (instancetype)shareInstance;
-
-- (void)showAlertInView:(UIView *)displayView callback:(CheckWiredCallback)callback;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 49
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/TipsAlert/NoWiredTipsAlert.m

@@ -1,49 +0,0 @@
-//
-//  NoWiredTipsAlert.m
-//  StudentDaya
-//
-//  Created by Kyle on 2021/12/12.
-//  Copyright © 2021 DayaMusic. All rights reserved.
-//
-
-#import "NoWiredTipsAlert.h"
-
-@interface NoWiredTipsAlert ()
-
-@property (nonatomic, copy) CheckWiredCallback callback;
-
-@end
-
-@implementation NoWiredTipsAlert
-
-+ (instancetype)shareInstance {
-    NoWiredTipsAlert *alert = [[[NSBundle mainBundle] loadNibNamed:@"NoWiredTipsAlert" owner:nil options:nil] firstObject];
-    return alert;
-}
-
-- (void)showAlertInView:(UIView *)displayView callback:(nonnull CheckWiredCallback)callback {
-    if (callback) {
-        self.callback = callback;
-    }
-    [displayView addSubview:self];
-}
-
-- (void)hiddenView {
-    [self removeFromSuperview];
-}
-- (IBAction)hiddenAlert:(id)sender {
-    [self hiddenView];
-    if (self.callback) {
-        self.callback();
-    }
-}
-
-/*
-// Only override drawRect: if you perform custom drawing.
-// An empty implementation adversely affects performance during animation.
-- (void)drawRect:(CGRect)rect {
-    // Drawing code
-}
-*/
-
-@end

+ 0 - 121
KulexiuForStudent/KulexiuForStudent/Module/CloudEngine/View/TipsAlert/NoWiredTipsAlert.xib

@@ -1,121 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
-    <device id="retina6_1" orientation="portrait" appearance="light"/>
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
-        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
-        <capability name="System colors in document resources" minToolsVersion="11.0"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <objects>
-        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
-        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="NoWiredTipsAlert">
-            <rect key="frame" x="0.0" y="0.0" width="663" height="423"/>
-            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-            <subviews>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ah5-xM-cyD">
-                    <rect key="frame" x="199.5" y="86.5" width="264" height="250"/>
-                    <subviews>
-                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="evaluate_logo" translatesAutoresizingMaskIntoConstraints="NO" id="qZY-An-3Kg">
-                            <rect key="frame" x="49" y="30" width="166" height="143"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="143" id="3in-lr-fgk"/>
-                                <constraint firstAttribute="width" constant="166" id="IFQ-Q4-07P"/>
-                            </constraints>
-                        </imageView>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="请佩戴耳机以保证测评准确率~" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ww5-Ot-JpL">
-                            <rect key="frame" x="32" y="169" width="200" height="17"/>
-                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                            <color key="textColor" red="0.50196078430000002" green="0.50196078430000002" blue="0.50196078430000002" alpha="1" colorSpace="calibratedRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="psJ-YC-Q92">
-                            <rect key="frame" x="74.5" y="198" width="115" height="34"/>
-                            <color key="backgroundColor" red="0.0039215686269999999" green="0.75686274509999996" blue="0.70980392160000005" alpha="1" colorSpace="calibratedRGB"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="34" id="Zgp-9F-Slx"/>
-                                <constraint firstAttribute="width" constant="115" id="pxl-hG-rB3"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
-                            <state key="normal" title="我知道了"/>
-                            <userDefinedRuntimeAttributes>
-                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                    <real key="value" value="17"/>
-                                </userDefinedRuntimeAttribute>
-                            </userDefinedRuntimeAttributes>
-                            <connections>
-                                <action selector="hiddenAlert:" destination="iN0-l3-epB" eventType="touchUpInside" id="3Qo-d6-rzW"/>
-                            </connections>
-                        </button>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="M3R-Ao-jkS">
-                            <rect key="frame" x="224" y="0.0" width="40" height="40"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="40" id="2jV-nA-GNI"/>
-                                <constraint firstAttribute="width" constant="40" id="YUL-Dj-pqb"/>
-                            </constraints>
-                            <state key="normal" image="check_cancle"/>
-                            <connections>
-                                <action selector="hiddenAlert:" destination="iN0-l3-epB" eventType="touchUpInside" id="e5e-J3-AiO"/>
-                            </connections>
-                        </button>
-                    </subviews>
-                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                    <constraints>
-                        <constraint firstItem="qZY-An-3Kg" firstAttribute="top" secondItem="ah5-xM-cyD" secondAttribute="top" constant="30" id="De8-6b-L70"/>
-                        <constraint firstAttribute="height" constant="250" id="KeG-CA-jys"/>
-                        <constraint firstItem="psJ-YC-Q92" firstAttribute="top" secondItem="Ww5-Ot-JpL" secondAttribute="bottom" constant="12" id="Qgm-um-k6z"/>
-                        <constraint firstAttribute="bottom" secondItem="psJ-YC-Q92" secondAttribute="bottom" constant="18" id="UCm-R8-q2q"/>
-                        <constraint firstAttribute="width" constant="264" id="bhW-0f-M08"/>
-                        <constraint firstItem="qZY-An-3Kg" firstAttribute="centerX" secondItem="ah5-xM-cyD" secondAttribute="centerX" id="jQI-en-d6F"/>
-                        <constraint firstAttribute="trailing" secondItem="M3R-Ao-jkS" secondAttribute="trailing" id="rNj-l9-iuh"/>
-                        <constraint firstItem="psJ-YC-Q92" firstAttribute="centerX" secondItem="ah5-xM-cyD" secondAttribute="centerX" id="uAS-Rq-Oqx"/>
-                        <constraint firstItem="M3R-Ao-jkS" firstAttribute="top" secondItem="ah5-xM-cyD" secondAttribute="top" id="w48-wT-LqO"/>
-                        <constraint firstItem="Ww5-Ot-JpL" firstAttribute="centerX" secondItem="ah5-xM-cyD" secondAttribute="centerX" id="zJm-80-LOi"/>
-                    </constraints>
-                    <userDefinedRuntimeAttributes>
-                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                            <real key="value" value="20"/>
-                        </userDefinedRuntimeAttribute>
-                    </userDefinedRuntimeAttributes>
-                </view>
-                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="image_alertTips" translatesAutoresizingMaskIntoConstraints="NO" id="8aD-n1-PzY">
-                    <rect key="frame" x="277.5" y="82.5" width="108" height="31"/>
-                    <constraints>
-                        <constraint firstAttribute="width" constant="108" id="1s5-7T-qTb"/>
-                        <constraint firstAttribute="height" constant="31" id="mJd-Tf-sEM"/>
-                    </constraints>
-                </imageView>
-                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="提示" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yjg-xn-pKL">
-                    <rect key="frame" x="315" y="88" width="33" height="20"/>
-                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
-                    <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                    <nil key="highlightedColor"/>
-                </label>
-            </subviews>
-            <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
-            <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
-            <constraints>
-                <constraint firstItem="8aD-n1-PzY" firstAttribute="top" secondItem="ah5-xM-cyD" secondAttribute="top" constant="-4" id="0PS-g0-dfi"/>
-                <constraint firstItem="yjg-xn-pKL" firstAttribute="centerX" secondItem="8aD-n1-PzY" secondAttribute="centerX" id="Py6-YQ-Ghs"/>
-                <constraint firstItem="ah5-xM-cyD" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="Uql-9x-IBE"/>
-                <constraint firstItem="yjg-xn-pKL" firstAttribute="centerY" secondItem="8aD-n1-PzY" secondAttribute="centerY" id="b07-Ty-0MM"/>
-                <constraint firstItem="8aD-n1-PzY" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="nAr-bf-6o6"/>
-                <constraint firstItem="ah5-xM-cyD" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="qI8-qZ-zsf"/>
-            </constraints>
-            <nil key="simulatedTopBarMetrics"/>
-            <nil key="simulatedBottomBarMetrics"/>
-            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
-            <point key="canvasLocation" x="136.95652173913044" y="-88.727678571428569"/>
-        </view>
-    </objects>
-    <resources>
-        <image name="check_cancle" width="14" height="14"/>
-        <image name="evaluate_logo" width="166" height="143"/>
-        <image name="image_alertTips" width="108" height="31"/>
-        <systemColor name="systemBackgroundColor">
-            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-        </systemColor>
-    </resources>
-</document>

+ 28 - 16
KulexiuForStudent/KulexiuForStudent/Module/Course/AccompanyCourse/Controller/AccompanyDetailViewController.m

@@ -592,25 +592,37 @@
 
 // 加入房间
 - (void)joinClassRoom {
+    
     // 加入房间前判断摄像头和麦克风逻辑
-    PREMISSIONTYPE micEnable = [RecordCheckManager checkMicPermissionAvaiable];
-    PREMISSIONTYPE cameraEnable = [RecordCheckManager checkCameraPremissionAvaiable];
-    if (micEnable == PREMISSIONTYPE_YES && cameraEnable == PREMISSIONTYPE_YES) {
-        // 进入教室
-        // 判断是否进行课前检测
-        [self.classManager joinRoomWithId:self.courseId subjectName:self.homeworkModel.subjectName classEndTime:self.homeworkModel.endTime inViewController:self];
-    }
-    else {
-        if (micEnable == PREMISSIONTYPE_NO && cameraEnable == PREMISSIONTYPE_NO) { // 如果麦克风权限和摄像头权限都没有
-            [self showAlertWithMessage:@"请开启相机和麦克风访问权限" type:CHECKDEVICETYPE_BOTH];
-        }
-        else if (micEnable == PREMISSIONTYPE_NO) { // 如果没有麦克风权限
-            [self showAlertWithMessage:@"请开启麦克风访问权限" type:CHECKDEVICETYPE_MIC];
+    [RecordCheckManager checkCameraPremissionAvaiableCallback:^(PREMISSIONTYPE type) {
+        [self afterCheckCameraCheckMic:type];
+    }];
+}
+
+- (void)afterCheckCameraCheckMic:(PREMISSIONTYPE)cameraType {
+    [RecordCheckManager checkMicPermissionAvaiableCallback:^(PREMISSIONTYPE type) {
+        if (type == PREMISSIONTYPE_YES && cameraType == PREMISSIONTYPE_YES) {
+            // 判断是否进行课前检测
+            [self.classManager joinRoomWithId:self.courseId subjectName:self.homeworkModel.subjectName classEndTime:self.homeworkModel.endTime inViewController:self];
         }
-        else if (cameraEnable == PREMISSIONTYPE_NO) { // 如果没有摄像头权限
-            [self showAlertWithMessage:@"请开启相机访问权限" type:CHECKDEVICETYPE_CAMREA];
+        else {
+            NSString *content = @"";
+            CHECKDEVICETYPE checkType = CHECKDEVICETYPE_BOTH;
+            if (cameraType == PREMISSIONTYPE_NO && type == PREMISSIONTYPE_NO) {
+                content = @"请开启相机和麦克风访问权限";
+                checkType = CHECKDEVICETYPE_BOTH;
+            }
+            else if (cameraType == PREMISSIONTYPE_NO && type == PREMISSIONTYPE_YES) {
+                content =  @"请开启相机访问权限";
+                checkType = CHECKDEVICETYPE_CAMREA;
+            }
+            else if (cameraType == PREMISSIONTYPE_YES && type == PREMISSIONTYPE_NO) {
+                content = @"请开启麦克风访问权限";
+                checkType = CHECKDEVICETYPE_MIC;
+            }
+            [self showAlertWithMessage:content type:checkType];
         }
-    }
+    }];    
 }
 
 - (void)showAlertWithMessage:(NSString *)message type:(CHECKDEVICETYPE)deviceType {

+ 28 - 17
KulexiuForStudent/KulexiuForStudent/Module/Course/MusicRoom/Controller/MusicRoomDetailViewController.m

@@ -515,26 +515,37 @@
 // 加入房间
 - (void)joinClassRoom {
     // 加入房间前判断摄像头和麦克风逻辑
-    PREMISSIONTYPE micEnable = [RecordCheckManager checkMicPermissionAvaiable];
-    PREMISSIONTYPE cameraEnable = [RecordCheckManager checkPhotoLibraryPremissionAvaiable];
-    if (micEnable == PREMISSIONTYPE_YES && cameraEnable == PREMISSIONTYPE_YES) {
-        // 进入教室
-        // 判断是否进行课前检测
-        [self.classManager joinRoomWithId:self.courseId subjectName:self.homeworkModel.subjectName classEndTime:self.homeworkModel.endTime inViewController:self];
-    }
-    else {
-        if (micEnable == PREMISSIONTYPE_NO && cameraEnable == PREMISSIONTYPE_NO) { // 如果麦克风权限和摄像头权限都没有
-            [self showAlertWithMessage:@"请开启相机和麦克风访问权限" type:CHECKDEVICETYPE_BOTH];
-        }
-        else if (micEnable == PREMISSIONTYPE_NO) { // 如果没有麦克风权限
-            [self showAlertWithMessage:@"请开启麦克风访问权限" type:CHECKDEVICETYPE_MIC];
+    [RecordCheckManager checkCameraPremissionAvaiableCallback:^(PREMISSIONTYPE type) {
+        [self afterCheckCameraCheckMic:type];
+    }];
+}
+
+- (void)afterCheckCameraCheckMic:(PREMISSIONTYPE)cameraType {
+    [RecordCheckManager checkMicPermissionAvaiableCallback:^(PREMISSIONTYPE type) {
+        if (type == PREMISSIONTYPE_YES && cameraType == PREMISSIONTYPE_YES) {
+            // 判断是否进行课前检测
+            [self.classManager joinRoomWithId:self.courseId subjectName:self.homeworkModel.subjectName classEndTime:self.homeworkModel.endTime inViewController:self];
         }
-        else if (cameraEnable == PREMISSIONTYPE_NO) { // 如果没有摄像头权限
-            [self showAlertWithMessage:@"请开启相机访问权限" type:CHECKDEVICETYPE_CAMREA];
+        else {
+            NSString *content = @"";
+            CHECKDEVICETYPE checkType = CHECKDEVICETYPE_BOTH;
+            if (cameraType == PREMISSIONTYPE_NO && type == PREMISSIONTYPE_NO) {
+                content = @"请开启相机和麦克风访问权限";
+                checkType = CHECKDEVICETYPE_BOTH;
+            }
+            else if (cameraType == PREMISSIONTYPE_NO && type == PREMISSIONTYPE_YES) {
+                content =  @"请开启相机访问权限";
+                checkType = CHECKDEVICETYPE_CAMREA;
+            }
+            else if (cameraType == PREMISSIONTYPE_YES && type == PREMISSIONTYPE_NO) {
+                content = @"请开启麦克风访问权限";
+                checkType = CHECKDEVICETYPE_MIC;
+            }
+            [self showAlertWithMessage:content type:checkType];
         }
-    }
+    }];
+    
 }
-
 - (void)showAlertWithMessage:(NSString *)message type:(CHECKDEVICETYPE)deviceType {
     [KSPremissionAlert shareInstanceDisplayImage:deviceType message:message showInView:self.view cancel:^{
         

+ 7 - 8
KulexiuForStudent/KulexiuForStudent/Module/Home/Controller/HomeViewController.m

@@ -1598,16 +1598,15 @@
 
 - (void)showScanView {
     // 判断是否有权限
-    PREMISSIONTYPE albumEnable = [RecordCheckManager checkCameraPremissionAvaiable];
-    if (albumEnable == PREMISSIONTYPE_YES) { // 如果有权限
-        KSScanViewController *ctrl = [[KSScanViewController alloc] init];
-        [self.navigationController pushViewController:ctrl animated:YES];
-    }
-    else {
-        if (albumEnable == PREMISSIONTYPE_NO) {
+    [RecordCheckManager checkCameraPremissionAvaiableCallback:^(PREMISSIONTYPE type) {
+        if (type == PREMISSIONTYPE_YES) {
+            KSScanViewController *ctrl = [[KSScanViewController alloc] init];
+            [self.navigationController pushViewController:ctrl animated:YES];
+        }
+        else {
             [self showAlertWithMessage:@"请开启相机访问权限" type:CHECKDEVICETYPE_CAMREA];
         }
-    }
+    }];
 }
 
 - (dispatch_group_t)requestGroup {

+ 7 - 8
KulexiuForStudent/KulexiuForStudent/Module/Mine/Controller/MineViewController.m

@@ -284,16 +284,15 @@
 
 - (void)scanAction {
     // 判断是否有权限
-    PREMISSIONTYPE albumEnable = [RecordCheckManager checkCameraPremissionAvaiable];
-    if (albumEnable == PREMISSIONTYPE_YES) { // 如果有权限
-        KSScanViewController *ctrl = [[KSScanViewController alloc] init];
-        [self.navigationController pushViewController:ctrl animated:YES];
-    }
-    else {
-        if (albumEnable == PREMISSIONTYPE_NO) {
+    [RecordCheckManager checkCameraPremissionAvaiableCallback:^(PREMISSIONTYPE type) {
+        if (type == PREMISSIONTYPE_YES) {
+            KSScanViewController *ctrl = [[KSScanViewController alloc] init];
+            [self.navigationController pushViewController:ctrl animated:YES];
+        }
+        else {
             [self showAlertWithMessage:@"请开启相机访问权限" type:CHECKDEVICETYPE_CAMREA];
         }
-    }
+    }];
 }
 
 - (void)showAlertWithMessage:(NSString *)message type:(CHECKDEVICETYPE)deviceType {

+ 6 - 8
KulexiuForStudent/KulexiuForStudent/Module/Mine/Scan/Controller/KSScanViewController.m

@@ -154,16 +154,14 @@
     }
     else {  // 选择相册
         // 判断是否有权限
-        PREMISSIONTYPE albumEnable = [RecordCheckManager checkPhotoLibraryPremissionAvaiable];
-        if (albumEnable == PREMISSIONTYPE_YES) { // 如果有权限
-            [self choosePhoneScan];
-        }
-        else {
-            if (albumEnable == PREMISSIONTYPE_NO) {
+        [RecordCheckManager checkPhotoLibraryPremissionAvaiableCallback:^(PREMISSIONTYPE type) {
+            if (type == PREMISSIONTYPE_YES) {
+                [self choosePhoneScan];
+            }
+            else {
                 [self showAlertWithMessage:@"请开启相册访问权限" type:CHECKDEVICETYPE_CAMREA];
             }
-        }
-        
+        }];
     }
 }
 - (void)showAlertWithMessage:(NSString *)message type:(CHECKDEVICETYPE)deviceType {

BIN
KulexiuForStudent/KulexiuForStudent/ToolKit/CloudAccompanyLibrary.framework/CloudAccompanyLibrary


+ 34 - 0
KulexiuForStudent/KulexiuForStudent/ToolKit/CloudAccompanyLibrary.framework/Headers/KSCloudWebViewController.h

@@ -10,6 +10,13 @@
 #import <KSToolLibrary/WeakWebViewScriptMessageDelegate.h>
 #import <KSToolLibrary/UINavigationController+KSNavigationBar.h>
 
+typedef NS_ENUM(NSInteger, CHECK_DELAY_TYPE) {
+    CHECK_DELAY_TYPE_START,
+    CHECK_DELAY_TYPE_FAILED,  // 失败
+    CHECK_DELAY_TYPE_SUCCESS, // 成功
+    CHECK_DELAY_TYPE_CANCEL,  // 取消延迟检测流程
+};
+
 @class KSCloudWebViewController;
 
 @protocol KSCloudWebViewControllerDelegate <NSObject>
@@ -40,6 +47,16 @@
 // 错误上报回调 ,额外需填写当前版本
 - (void)cloudPageOccourError:(NSMutableDictionary *_Nonnull)uploadParm;
 
+
+#pragma mark ----- 延迟检测相关
+// 显示延迟检测
+- (void)showDelayCheckViewDisplay:(UIView *_Nonnull)displayView callBackController:(KSCloudWebViewController *_Nonnull)controller;
+// 修改检测状态
+- (void)changeDelayCheckStatus:(CHECK_DELAY_TYPE)checkStatus;
+// 回调当前耳机状态
+- (void)displayCurrentHeadsetTypes:(NSDictionary *_Nonnull)parm;
+// socket连接成功回调
+- (void)socketConnectedCallback;
 @end
 
 NS_ASSUME_NONNULL_BEGIN
@@ -81,6 +98,23 @@ NS_ASSUME_NONNULL_BEGIN
 
 // 合成完成后回调
 - (void)musicPublishCallBack;
+// 重播
+- (void)retryEvaluatingMusic;
+
+- (void)checkAudioType;
+// socket是否连接上
+- (BOOL)isSocketConnected;
+
+// 开始App延迟检测
+- (void)startAppDelayCheck;
+// 取消延迟检测流程
+- (void)cancelAppDelayCheck;
+// 延迟检测中断
+- (void)checkDelayBreak;
+
+- (void)finishDelayCheck;
+
+- (void)connectSocket;
 
 @end
 

BIN
KulexiuForStudent/KulexiuForStudent/ToolKit/CloudAccompanyLibrary.framework/_CodeSignature/CodeDirectory


BIN
KulexiuForStudent/KulexiuForStudent/ToolKit/CloudAccompanyLibrary.framework/_CodeSignature/CodeRequirements-1


+ 3 - 3
KulexiuForStudent/KulexiuForStudent/ToolKit/CloudAccompanyLibrary.framework/_CodeSignature/CodeResources

@@ -58,7 +58,7 @@
 		</data>
 		<key>Headers/KSCloudWebViewController.h</key>
 		<data>
-		pZOk0rtmzLtLAH9cSM9y5V6aZ/k=
+		zdPduXm8/0MzlDLm3KlHZ6du4GI=
 		</data>
 		<key>Headers/KSVideoRecordManager.h</key>
 		<data>
@@ -222,11 +222,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			pZOk0rtmzLtLAH9cSM9y5V6aZ/k=
+			zdPduXm8/0MzlDLm3KlHZ6du4GI=
 			</data>
 			<key>hash2</key>
 			<data>
-			RO0ZS6NoI6TZn40r/kX+ncngS2X+PI+xR65M5qT1qUs=
+			UT4btEVKKOf+tZgqaS8Lp6gJWWQh+a6BsV/MWK1hAuQ=
 			</data>
 		</dict>
 		<key>Headers/KSVideoRecordManager.h</key>

BIN
KulexiuForStudent/KulexiuForStudent/ToolKit/CloudAccompanyLibrary.framework/_CodeSignature/CodeSignature


+ 0 - 1
KulexiuForStudent/KulexiuForStudent/ToolKit/KSToolLibrary.framework/Headers/KSAQRecordManager.h

@@ -9,7 +9,6 @@
 #import <Foundation/Foundation.h>
 #import <KSToolLibrary/KSAudioSessionManager.h>
 
-
 NS_ASSUME_NONNULL_BEGIN
 
 @class KSAQRecordManager;

+ 7 - 3
KulexiuForStudent/KulexiuForStudent/ToolKit/KSToolLibrary.framework/Headers/RecordCheckManager.h

@@ -14,13 +14,17 @@ typedef NS_ENUM(NSInteger, PREMISSIONTYPE) {
     PREMISSIONTYPE_YES,
 };
 
+typedef void(^RecordCheckCallback)(PREMISSIONTYPE type);
+
 NS_ASSUME_NONNULL_BEGIN
 
 @interface RecordCheckManager : NSObject
 
-+ (PREMISSIONTYPE)checkMicPermissionAvaiable;
-+ (PREMISSIONTYPE)checkCameraPremissionAvaiable;
-+ (PREMISSIONTYPE)checkPhotoLibraryPremissionAvaiable;
++ (void)checkMicPermissionAvaiableCallback:(RecordCheckCallback)callback;
+
++ (void)checkCameraPremissionAvaiableCallback:(RecordCheckCallback)callback;
+
++ (void)checkPhotoLibraryPremissionAvaiableCallback:(RecordCheckCallback)callback;
 
 @end
 

BIN
KulexiuForStudent/KulexiuForStudent/ToolKit/KSToolLibrary.framework/KSToolLibrary