- 合并样式【渐变线】到【线】,【线】与【波浪】新增方向(水平与垂直)设置选项

- 样式【波浪】、【圆】、【实心圆】添加渐变设置选项
- 优化服务器调试逻辑(调试模式:服务器崩溃自动打开日志文件)
- 优化API
This commit is contained in:
mashiros 2022-06-04 01:37:58 +08:00
parent 4f9e8d57c5
commit beffc3a791
23 changed files with 1234 additions and 728 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map>
<value name="current_style">"nvg://advp.widget.mashiros.top/advp-style-preset/circle"</value>
<value name="nvg://advp.widget.mashiros.top/advp-style-preset/circle">{"Main Color":"#ff4500","Line Position":0,"Line Width":1,"Max Range":50,"Data Length":0,"Channel":2,"Reverse":false,"Rotate":false,"Ratate Speed":10,"Angle":0,"Data Settings":{"Auto Normalizing":true,"Amplitude":10,"Unit Style":0}}</value>
<value name="nvg://advp.widget.mashiros.top/advp-style-preset/circle">{"Gradient Style":0,"Radial Gradient Settings":{"Inside Position Color":"#f44336","Middle Position Color":"#4caf50","Outside Position Color":"#03a9f4","Inside Position":40,"Middle Position":60,"Outside Position":80},"Conical Gradient Settings":{"Start Position Color":"#f44336","Quarter Position Color":"#4caf50","Middle Position Color":"#03a9f4","End Position Color":"#ffeb3b"},"Main Color":"#ff4500","Line Position":0,"Line Width":1,"Max Range":80,"Data Length":0,"Channel":2,"Reverse":false,"Rotate":false,"Ratate Speed":10,"Angle":0,"Data Settings":{"Auto Normalizing":true,"Amplitude":10,"Unit Style":0}}</value>
</map>

View File

@ -1,4 +0,0 @@
{
"source": "nvg://advp.widget.mashiros.top/widget",
"settings": "settings.xml"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<map>
<value name="current_style">"nvg://advp.widget.mashiros.top/advp-style-preset/gradient_line"</value>
<value name="nvg://advp.widget.mashiros.top/advp-style-preset/gradient_line">{"Gradient Direction":0,"Start Position Color":"#f44336","Middle Position Color":"#4caf50","End Position Color":"#03a9f4","Center Line":true,"Line Position":0,"Data Length":0,"Channel":2,"Rotate Settings":{"Center Enable":false,"Center Angle":10,"Line Enable":false,"Line Angle":10},"Data Settings":{"Auto Normalizing":true,"Amplitude":10,"Unit Style":0}}</value>
</map>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map>
<value name="nvg://advp.widget.mashiros.top/advp-style-preset/line">{"Center Line":true,"Center Color":"#ff4500","Line Color":"#ff4500","Line Position":0,"Data Length":0,"Channel":2,"Rotate Settings":{"Center Enable":false,"Center Angle":10,"Line Enable":false,"Line Angle":10},"Data Settings":{"Auto Normalizing":true,"Amplitude":10,"Unit Style":0}}</value>
<value name="nvg://advp.widget.mashiros.top/advp-style-preset/line">{"Enable Gradient":false,"Gradient Direction":0,"Start Position Color":"#f44336","Middle Position Color":"#4caf50","End Position Color":"#03a9f4","Center Line":true,"Center Color":"#ff4500","Center Width":20,"Line Color":"#ff4500","Line Position":0,"Data Length":0,"Channel":2,"Direction":0,"Rotate Settings":{"Center Enable":false,"Center Angle":10,"Line Enable":false,"Line Angle":10,"X Scale":100,"Y Scale":100,"X Offset":0,"Y Offset":0},"Data Settings":{"Auto Normalizing":true,"Amplitude":10,"Unit Style":0}}</value>
<value name="current_style">"nvg://advp.widget.mashiros.top/advp-style-preset/line"</value>
</map>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map>
<value name="current_style">"nvg://advp.widget.mashiros.top/advp-style-preset/solidcircle"</value>
<value name="nvg://advp.widget.mashiros.top/advp-style-preset/solidcircle">{"Main Color":"#ff4500","Line Position":0,"Line Width":1,"Max Range":50,"Data Length":0,"Channel":2,"Reverse":false,"Rotate":false,"Ratate Speed":10,"Angle":0,"Data Settings":{"Auto Normalizing":true,"Amplitude":10,"Unit Style":0}}</value>
<value name="nvg://advp.widget.mashiros.top/advp-style-preset/solidcircle">{"Gradient Style":0,"Radial Gradient Settings":{"Inside Position Color":"#f44336","Middle Position Color":"#4caf50","Outside Position Color":"#03a9f4","Inside Position":40,"Middle Position":60,"Outside Position":80},"Conical Gradient Settings":{"Start Position Color":"#f44336","Quarter Position Color":"#4caf50","Middle Position Color":"#03a9f4","End Position Color":"#ffeb3b"},"Main Color":"#ff4500","Line Position":0,"Line Width":1,"Max Range":80,"Data Length":0,"Channel":2,"Reverse":false,"Rotate":false,"Ratate Speed":10,"Angle":0,"Data Settings":{"Auto Normalizing":true,"Amplitude":10,"Unit Style":0}}</value>
</map>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map>
<value name="current_style">"nvg://advp.widget.mashiros.top/advp-style-preset/waves"</value>
<value name="nvg://advp.widget.mashiros.top/advp-style-preset/waves">{"Line Width":1,"Line Color":"#ff4500","Data Length":0,"Data Settings":{"Auto Normalizing":true,"Amplitude":10,"Unit Style":0}}</value>
<value name="nvg://advp.widget.mashiros.top/advp-style-preset/waves">{"Enable Gradient":false,"Gradient Direction":0,"Start Position Color":"#f44336","Middle Position Color":"#4caf50","End Position Color":"#03a9f4","Direction":0,"Line Color":"#ff4500","Line Width":1,"Data Length":0,"Rotate Settings":{"Center Enable":false,"Center Angle":10,"Line Enable":false,"Line Angle":10,"X Scale":100,"Y Scale":100,"X Offset":0,"Y Offset":0},"Data Settings":{"Auto Normalizing":true,"Amplitude":10,"Unit Style":0}}</value>
</map>

View File

@ -1,6 +1,6 @@
{
{
"name": "top.mashiros.widget.advp",
"version": "1.3.0",
"version": "1.4.0",
"title": {
"en": "ADV Plugin",
@ -61,17 +61,6 @@
},
"entry": "./styles/Preset_line/Style.qml"
},
{
"location": "/advp-style-preset/gradient_line",
"catalog": "top.mashiros.advp-style",
"title": {
"en": "Gradient Line",
"zh": "渐变线",
"zh_TW": "漸變線",
"ja": "グラデーションライン"
},
"entry": "./styles/Preset_gradient_line/Style.qml"
},
{
"location": "/advp-style-preset/waves",
"catalog": "top.mashiros.advp-style",
@ -187,6 +176,17 @@
},
"preview": "Presets/Ordinal_Scale_UI_bottom/preview.png",
"entry": "Presets/Ordinal_Scale_UI_bottom/preset.json"
},
{
"location": "/advp-style-preset/gradient_line",
"catalog": "top.mashiros.advp-style-temp",
"title": {
"en": "Gradient Line",
"zh": "渐变线",
"zh_TW": "漸變線",
"ja": "グラデーションライン"
},
"entry": "./styles/Preset_line/Style.qml"
}
]
}

View File

@ -128,6 +128,8 @@ Item {
for (let prop in sourceObj) {
if (sourceObj.hasOwnProperty(prop) && sourceObj[prop] !== undefined) {
if (typeof sourceObj[prop] === 'object') {
if (targetObj[prop] === undefined)
targetObj[prop] = {};
Object.assign(targetObj[prop], sourceObj[prop]);
} else {
targetObj[prop] = sourceObj[prop];

View File

@ -37,12 +37,6 @@ T.Widget {
preference = item.preference;
defaultValues = item.defaultValues;
style = item.style;
if (!widget.settings[widget.settings.current_style]) {
widget.settings[widget.settings.current_style] = defaultValues;
}else if(widget.settings[widget.settings.current_style]["Version"] !== defaultValues["Version"]) {
delete widget.settings[widget.settings.current_style]["Version"];
widget.settings[widget.settings.current_style] = Common.updateObject(Common.deepClone(defaultValues), widget.settings[widget.settings.current_style]);
}
}
}
@ -72,7 +66,7 @@ T.Widget {
Component.onCompleted: {
Common.widgetsNum++;
if ((!widget.settings.current_style) || (Common.stylesURL.indexOf(widget.settings.current_style) === -1)) {
if (!widget.settings.current_style) {
widget.settings.current_style = Common.stylesURL[0];
}
}

View File

@ -11,8 +11,20 @@ Canvas {
signal audioDataUpdeted(var data)
signal configsUpdated()
signal completed()
signal versionUpdated(string old)
readonly property var configs: widget.settings[widget.settings.current_style] ?? defaultValues
function updateObject(target, source) {
return Common.updateObject(Common.deepClone(target), Common.deepClone(source));
}
onVersionUpdated: {
delete widget.settings[widget.settings.current_style]["Version"];
widget.settings[widget.settings.current_style] = updateObject(defaultValues, widget.settings[widget.settings.current_style]);
}
onConfigsChanged: {
if (context) {
configsUpdated();
@ -30,4 +42,13 @@ Canvas {
target: Common
onAudioDataUpdated: audioDataUpdeted(audioData)
}
Component.onCompleted: {
if (!widget.settings[widget.settings.current_style]) {
widget.settings[widget.settings.current_style] = defaultValues;
}else if(widget.settings[widget.settings.current_style]["Version"] !== defaultValues["Version"]) {
versionUpdated(widget.settings[widget.settings.current_style]["Version"]);
}
completed();
}
}

View File

@ -12,7 +12,7 @@
## 特色
* 整合客户端与服务器端的功能,使用更简单
* 预设6种频谱显示形式,其中每种都可以进一步自定义设置其样式
* 预设5种频谱显示形式,其中每种都可以进一步自定义设置其样式
* 提供了Style的开发接口供开发者添加更多的可视化样式
* 导入第三方Style类似其他插件预计支持steam创意工坊下载
* 服务端崩溃后自启动
@ -21,7 +21,7 @@
安装并启用插件后默认加载第一种预设Style样式。右键点击挂件可调出菜单在挂件菜单中点击“样式设置...”选项,呼出样式设置窗口。点击其中的样式选项可切换不同的样式风格,若此样式提供可配置项,则在样式选项下方会出现配置项。
<div align="center"><img src="https://s3.bmp.ovh/imgs/2022/05/25/ad36cd0eccc8dd61.png" style="zoom:80%;" /></div>
<div align="center"><img src="https://s3.bmp.ovh/imgs/2022/06/04/b608a46f85afc715.png" style="zoom:80%;" /></div>
## 服务器设置

View File

@ -110,7 +110,7 @@ AdvpStyleTemplate {
requestPaint();
}
Component.onCompleted: {
onCompleted: {
for (let i = 0; i < 128; i++) {
audioData[i] = 0;
}

View File

@ -1,115 +1,185 @@
import QtQuick 2.12
import QtGraphicalEffects 1.12
import NERvGear.Preferences 1.0 as P
import "../../qml/api"
AdvpStyleTemplate {
style: AdvpCanvasTemplate {
readonly property var audioData: new Array(128)
style: Rectangle {
id: main
width: widget.width;
height: widget.height;
//configs
readonly property int linePosition: configs["Line Position"]
readonly property real maxRange: configs["Max Range"] / 100
readonly property int uDataLen: Math.pow(2, configs["Data Length"])
readonly property int dataLength: 64/uDataLen
readonly property int channel: configs["Channel"]
readonly property bool reverse: configs["Reverse"]
readonly property bool rotateFlag: configs["Rotate"]
readonly property real rSpeed: configs["Ratate Speed"] / 100
readonly property real angle: configs["Angle"]
readonly property bool autoNormalizing: configs["Data Settings"]["Auto Normalizing"]
readonly property real amplitude: 400/configs["Data Settings"]["Amplitude"]
readonly property int unitStyle: configs["Data Settings"]["Unit Style"]
property int gradientStyle
readonly property int total: channel*dataLength
readonly property real dotGap: 360/total
property real offsetAngle: 0
property var outerPos: []
property var innerPos: []
readonly property real degUnit: Math.PI/180
readonly property real subRatio: 0.2*maxRange
readonly property real mainRatio: 1-subRatio*2.5
readonly property real minLength: Math.min(width, height)
readonly property real ratio:minLength*subRatio
readonly property real halfWidth: width/2
readonly property real halfHeight: height/2
readonly property real halfMinLength: minLength/2
onConfigsUpdated: {
context.lineWidth = configs["Line Width"];
context.strokeStyle = configs["Main Color"];
}
function createPoint() {
outerPos.length = 0;
innerPos.length = 0;
let deg, deltaR, r1, r2, _rhmLen;
_rhmLen = mainRatio*halfMinLength;
for (let j=0; j < channel; j++) {
for (let i=0; i < dataLength; i++) {
deg = degUnit*((i+j*dataLength)*dotGap + offsetAngle);
deltaR = audioData[reverse*(dataLength-i-1)+(!reverse)*(i+j*dataLength)] * ratio;
r1 = _rhmLen+1+deltaR*(linePosition!==2);
r2 = _rhmLen-1-deltaR*(linePosition!==1);
outerPos.push([halfWidth+Math.cos(deg)*r1,halfHeight+Math.sin(deg)*r1]);
innerPos.push([halfWidth+Math.cos(deg)*r2,halfHeight+Math.sin(deg)*r2]);
}
RadialGradient {
id: radialGradient
anchors.fill: parent
visible: gradientStyle===1
horizontalRadius: Math.min(width, height)/2
verticalRadius: horizontalRadius
gradient: Gradient {
GradientStop {id: radialGradient_pstart}
GradientStop {id: radialGradient_pmiddle}
GradientStop {id: radialGradient_pend}
}
offsetAngle = rotateFlag ? ((offsetAngle + rSpeed) % 360) : angle;
}
onAudioDataUpdeted: {
let normalizing_ratio = autoNormalizing ? data[128] : amplitude;
if (unitStyle) {
//
for(let i=0; i<total; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += Math.max(0, 0.4 * (Math.log10(data[i*uDataLen+j]/normalizing_ratio)) + 1.0);
ConicalGradient {
id: conicalGradient
anchors.fill: parent
visible: gradientStyle===2
angle: -90;
gradient: Gradient {
GradientStop{id: conicalGradient_pstart; position: 0.0}
GradientStop{id: conicalGradient_pquarter; position: 0.25}
GradientStop {id: conicalGradient_phalf; position: 0.5}
GradientStop {id: conicalGradient_p3quarter; position: 0.75}
GradientStop{id: conicalGradient_pend; position: 1.0}
}
}
layer.enabled: true
layer.effect: OpacityMask{
maskSource: AdvpCanvasTemplate {
readonly property var audioData: new Array(128)
//configs
readonly property int linePosition: configs["Line Position"]
readonly property real maxRange: configs["Max Range"] / 100
readonly property int uDataLen: Math.pow(2, configs["Data Length"])
readonly property int dataLength: 64/uDataLen
readonly property int channel: configs["Channel"]
readonly property bool reverse: configs["Reverse"]
readonly property bool rotateFlag: configs["Rotate"]
readonly property real rSpeed: configs["Ratate Speed"] / 100
readonly property real angle: configs["Angle"]
readonly property bool autoNormalizing: configs["Data Settings"]["Auto Normalizing"]
readonly property real amplitude: 400/configs["Data Settings"]["Amplitude"]
readonly property int unitStyle: configs["Data Settings"]["Unit Style"]
readonly property int total: channel*dataLength
readonly property real dotGap: 360/total
property real offsetAngle: 0
property var outerPos: []
property var innerPos: []
readonly property real degUnit: Math.PI/180
readonly property real subRatio: 0.2*maxRange
readonly property real mainRatio: 1-subRatio*2.5
readonly property real minLength: Math.min(width, height)
readonly property real ratio:minLength*subRatio
readonly property real halfWidth: width/2
readonly property real halfHeight: height/2
readonly property real halfMinLength: minLength/2
onConfigsUpdated: {
gradientStyle = configs["Gradient Style"];
context.lineWidth = configs["Line Width"];
main.color = configs["Main Color"];
if (gradientStyle === 1) {
radialGradient_pstart.color = configs["Radial Gradient Settings"]["Inside Position Color"];
radialGradient_pstart.position = configs["Radial Gradient Settings"]["Inside Position"]/100;
radialGradient_pmiddle.color = configs["Radial Gradient Settings"]["Middle Position Color"];
radialGradient_pmiddle.position = configs["Radial Gradient Settings"]["Middle Position"]/100;
radialGradient_pend.color = configs["Radial Gradient Settings"]["Outside Position Color"];
radialGradient_pend.position = configs["Radial Gradient Settings"]["Outside Position"]/100;
} else if (gradientStyle === 2) {
conicalGradient_pstart.color = configs["Conical Gradient Settings"]["Start Position Color"];
conicalGradient_pquarter.color = configs["Conical Gradient Settings"]["Quarter Position Color"];
conicalGradient_phalf.color = configs["Conical Gradient Settings"]["Middle Position Color"];
conicalGradient_p3quarter.color = configs["Conical Gradient Settings"]["End Position Color"];
conicalGradient_pend.color = configs["Conical Gradient Settings"]["Start Position Color"];
}
audioData[i] /= uDataLen;
}
} else {
//线
for(let i=0; i<total; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += data[i*uDataLen+j];
function createPoint() {
outerPos.length = 0;
innerPos.length = 0;
let deg, deltaR, r1, r2, _rhmLen;
_rhmLen = mainRatio*halfMinLength;
for (let j=0; j < channel; j++) {
for (let i=0; i < dataLength; i++) {
deg = degUnit*((i+j*dataLength)*dotGap+offsetAngle);
deltaR = audioData[reverse*(dataLength-i-1)+(!reverse)*(i+j*dataLength)] * ratio;
r1 = _rhmLen+1+deltaR*(linePosition!==2);
r2 = _rhmLen-1-deltaR*(linePosition!==1);
outerPos.push([halfWidth+Math.cos(deg)*r1,halfHeight+Math.sin(deg)*r1]);
innerPos.push([halfWidth+Math.cos(deg)*r2,halfHeight+Math.sin(deg)*r2]);
}
}
audioData[i] /= (uDataLen * normalizing_ratio);
conicalGradient.rotation = offsetAngle;
offsetAngle = rotateFlag ? ((offsetAngle + rSpeed) % 360) : angle;
}
}
context.clearRect(0, 0, width+32, height+32);
createPoint();
onAudioDataUpdeted: {
let normalizing_ratio = autoNormalizing ? data[128] : amplitude;
if (unitStyle) {
//
for(let i=0; i<total; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += Math.max(0, 0.4 * (Math.log10(data[i*uDataLen+j]/normalizing_ratio)) + 1.0);
}
audioData[i] /= uDataLen;
}
} else {
//线
for(let i=0; i<total; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += data[i*uDataLen+j];
}
audioData[i] /= (uDataLen * normalizing_ratio);
}
}
context.beginPath();
for(let i=0; i<total; i++) {
context.moveTo(outerPos[i][0], outerPos[i][1]);
context.lineTo(innerPos[i][0], innerPos[i][1]);
}
context.stroke();
requestPaint();
}
context.clearRect(0, 0, width+32, height+32);
createPoint();
Component.onCompleted: {
for (let i = 0; i < 128; i++) {
audioData[i] = 0;
context.beginPath();
for(let i=0; i<total; i++) {
context.moveTo(outerPos[i][0], outerPos[i][1]);
context.lineTo(innerPos[i][0], innerPos[i][1]);
}
context.stroke();
requestPaint();
}
onCompleted: {
for (let i = 0; i < 128; i++) {
audioData[i] = 0;
}
}
}
}
}
defaultValues: {
"Version": "1.1.0",
"Version": "1.2.0",
"Gradient Style": 0,
"Radial Gradient Settings": {
"Inside Position Color": "#f44336",
"Middle Position Color": "#4caf50",
"Outside Position Color": "#03a9f4",
"Inside Position": 40,
"Middle Position": 60,
"Outside Position": 80
},
"Conical Gradient Settings": {
"Start Position Color": "#f44336",
"Quarter Position Color": "#4caf50",
"Middle Position Color": "#03a9f4",
"End Position Color": "#ffeb3b"
},
"Main Color": "#ff4500",
"Line Position": 0,
"Line Width": 1,
"Max Range": 50,
"Max Range": 80,
"Data Length": 0,
"Channel": 2,
"Reverse": false,
@ -126,9 +196,107 @@ AdvpStyleTemplate {
preference: AdvpPreference {
version: defaultValues["Version"]
P.SelectPreference {
id: _cfg_gradient_style
name: "Gradient Style"
label: qsTr("Gradient Style")
defaultValue: defaultValues["Gradient Style"]
model: [qsTr("None"), qsTr("Radial Gradient"), qsTr("Conical Gradient")]
}
P.DialogPreference {
name: "Radial Gradient Settings"
label: qsTr("Radial Gradient Settings")
live: true
visible: _cfg_gradient_style.value===1
P.ColorPreference {
name: "Inside Position Color"
label: qsTr("Inside Position Color")
defaultValue: defaultValues["Radial Gradient Settings"]["Inside Position Color"]
}
P.ColorPreference {
name: "Middle Position Color"
label: qsTr("Middle Position Color")
defaultValue: defaultValues["Radial Gradient Settings"]["Middle Position Color"]
}
P.ColorPreference {
name: "Outside Position Color"
label: qsTr("Outside Position Color")
defaultValue: defaultValues["Radial Gradient Settings"]["Outside Position Color"]
}
P.SliderPreference {
id: _cfg_gradient_settings_inside_position
name: "Inside Position"
label: qsTr("Inside Position")
from: 0
to: 75
stepSize: 1
defaultValue: defaultValues["Radial Gradient Settings"]["Inside Position"]
displayValue: value + "%"
}
P.SliderPreference {
id: _cfg_gradient_settings_middle_position
name: "Middle Position"
label: qsTr("Middle Position")
from: _cfg_gradient_settings_inside_position.value + 1
to: 90
stepSize: 1
defaultValue: defaultValues["Radial Gradient Settings"]["Middle Position"]
displayValue: value + "%"
}
P.SliderPreference {
name: "Outside Position"
label: qsTr("Outside Position")
from: _cfg_gradient_settings_middle_position.value + 1
to: 100
stepSize: 1
defaultValue: defaultValues["Radial Gradient Settings"]["Outside Position"]
displayValue: value + "%"
}
}
P.DialogPreference {
name: "Conical Gradient Settings"
label: qsTr("Conical Gradient Settings")
live: true
visible: _cfg_gradient_style.value===2
P.ColorPreference {
name: "Start Position Color"
label: qsTr("Start Position Color")
defaultValue: defaultValues["Conical Gradient Settings"]["Start Position Color"]
}
P.ColorPreference {
name: "Quarter Position Color"
label: qsTr("Quarter Position Color")
defaultValue: defaultValues["Conical Gradient Settings"]["Quarter Position Color"]
}
P.ColorPreference {
name: "Middle Position Color"
label: qsTr("Middle Position Color")
defaultValue: defaultValues["Conical Gradient Settings"]["Middle Position Color"]
}
P.ColorPreference {
name: "End Position Color"
label: qsTr("End Position Color")
defaultValue: defaultValues["Conical Gradient Settings"]["End Position Color"]
}
}
P.ColorPreference {
name: "Main Color"
label: qsTr("Spectrum Line Color")
visible: !_cfg_gradient_style.value
defaultValue: defaultValues["Main Color"]
}
@ -179,8 +347,6 @@ AdvpStyleTemplate {
defaultValue: defaultValues["Channel"]
}
P.Separator {}
P.SwitchPreference {
name: "Reverse"
label: qsTr("Reverse Spectrum")

View File

@ -1,310 +0,0 @@
import QtQuick 2.12
import QtGraphicalEffects 1.12
import NERvGear.Preferences 1.0 as P
import "../../qml/api"
AdvpStyleTemplate {
style: Rectangle {
width: widget.width;
height: widget.height;
LinearGradient {
id: gradient_mask
anchors.fill: parent
gradient: Gradient {
GradientStop { id: p_start; position: 0.0 }
GradientStop { id: p_middle; position: 0.5 }
GradientStop { id: p_end; position: 1.0 }
}
}
layer.enabled: true
layer.effect: OpacityMask{
maskSource: AdvpCanvasTemplate {
readonly property var audioData: new Array(128)
readonly property bool centerLineFlag: configs["Center Line"]
readonly property int linePosition: configs["Line Position"]
readonly property int uDataLen: Math.pow(2, configs["Data Length"]);
readonly property int dataLength: 64/uDataLen
readonly property int channel: configs["Channel"]
readonly property bool centerRotateFlag: configs["Rotate Settings"]["Center Enable"]
readonly property real centerRotateAngle: configs["Rotate Settings"]["Center Angle"]*Math.PI/180
readonly property bool lineRotateFlag: configs["Rotate Settings"]["Line Enable"]
readonly property real lineRotateAngle: configs["Rotate Settings"]["Line Angle"]*Math.PI/180
readonly property bool autoNormalizing: configs["Data Settings"]["Auto Normalizing"]
readonly property real amplitude: 400.0/configs["Data Settings"]["Amplitude"]
readonly property int unitStyle: configs["Data Settings"]["Unit Style"]
property real halfWidth: width/2
property real halfHeight: height/2
readonly property int l_start: (channel===1)*dataLength
readonly property int r_stop: dataLength+dataLength*(channel!==0)
readonly property int total: r_stop-l_start
readonly property real _y_dy: centerRotateFlag*Math.tan(centerRotateAngle)*halfWidth
readonly property real _ux: width/(r_stop-l_start)
readonly property real _dx: Math.round(_ux/2)
onConfigsUpdated: {
context.fillStyle = "black";
gradient_mask.start = Qt.point(0, height*(configs["Gradient Direction"]===2))
gradient_mask.end = Qt.point(width*(configs["Gradient Direction"]!==1), height*(configs["Gradient Direction"]%2))
p_start.color = configs["Start Position Color"];
p_middle.color = configs["Middle Position Color"];
p_end.color = configs["End Position Color"];
}
onAudioDataUpdeted: {
let normalizing_ratio = autoNormalizing ? data[128] : amplitude;
if (unitStyle) {
//
for(let i=l_start; i<dataLength; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += Math.max(0, 0.4 * (Math.log10(data[63-i*uDataLen-j]/normalizing_ratio)) + 1.0);
}
audioData[i] /= uDataLen;
}
for(let i=dataLength; i<r_stop; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += Math.max(0, 0.4 * (Math.log10(data[i*uDataLen+j]/normalizing_ratio)) + 1.0);
}
audioData[i] /= uDataLen;
}
} else {
//线
for(let i=l_start; i<dataLength; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += data[63-i*uDataLen-j];
}
audioData[i] /= (uDataLen * normalizing_ratio);
}
for(let i=dataLength; i<r_stop; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += data[i*uDataLen+j];
}
audioData[i] /= (uDataLen * normalizing_ratio);
}
}
context.clearRect(0, 0, width+32, height+32);
let _y;
let _dy;
//
if(lineRotateFlag || centerRotateFlag) {
context.transform(1, Math.sin(centerRotateFlag*centerRotateAngle), -Math.sin(lineRotateFlag*lineRotateAngle), 1, Math.sin(lineRotateFlag*lineRotateAngle)*(halfHeight-_y_dy), 0);
for (let i=l_start; i<r_stop; i++) {
_y = halfHeight*(1-(linePosition!==2)*audioData[i])-_y_dy;
_dy = (halfHeight + (!linePosition)*halfHeight)*audioData[i];
context.fillRect(_ux * (i-l_start), _y, _dx, _dy);
}
if (centerLineFlag) {
context.fillRect(0, halfHeight-_y_dy, width, 2);
}
context.resetTransform();
} else if (linePosition) {
let _flag = 1-2*(linePosition===1);
_y = halfHeight + halfHeight*(3-2*linePosition)*Boolean(linePosition);
for (let i=l_start; i<r_stop; i++) {
_dy = height*audioData[i]*_flag;
context.fillRect(_ux * (i-l_start), _y, _dx, _dy);
}
if (centerLineFlag) {
context.fillRect(0, _y-(2-linePosition)*2, width, 2);
}
} else {
for (let i=l_start; i<r_stop; i++) {
_y = halfHeight*(1-(linePosition!==2)*audioData[i])-_y_dy;
_dy = (halfHeight + (!linePosition)*halfHeight)*audioData[i];
context.fillRect(_ux * (i-l_start), _y, _dx, _dy);
}
if (centerLineFlag) {
context.fillRect(0, halfHeight-_y_dy, width, 2);
}
}
context.fill();
requestPaint();
}
Component.onCompleted: {
for (let i = 0; i < 128; i++) {
audioData[i] = 0;
}
}
}
}
}
defaultValues: {
"Version": "1.2.0",
"Gradient Direction": 0,
"Start Position Color": "#f44336",
"Middle Position Color": "#4caf50",
"End Position Color": "#03a9f4",
"Center Line": true,
"Line Position": 0,
"Data Length": 0,
"Channel": 2,
"Rotate Settings": {
"Center Enable": false,
"Center Angle": 10,
"Line Enable": false,
"Line Angle": 10
},
"Data Settings": {
"Auto Normalizing": true,
"Amplitude": 10,
"Unit Style": 0
}
}
preference: AdvpPreference {
version: defaultValues["Version"]
P.SelectPreference {
name: "Gradient Direction"
label: qsTr("Gradient Direction")
defaultValue: defaultValues["Gradient Direction"]
model: [qsTr("Horizontal"), qsTr("Vertical"), qsTr("Oblique Upward"), qsTr("Oblique downward")]
}
P.ColorPreference {
name: "Start Position Color"
label: qsTr("Start Position Color")
defaultValue: defaultValues["Start Position Color"]
}
P.ColorPreference {
name: "Middle Position Color"
label: qsTr("Middle Position Color")
defaultValue: defaultValues["Middle Position Color"]
}
P.ColorPreference {
name: "End Position Color"
label: qsTr("End Position Color")
defaultValue: defaultValues["End Position Color"]
}
P.Separator {}
P.SwitchPreference {
name: "Center Line"
label: qsTr("Show Center Line")
defaultValue: defaultValues["Center Line"]
}
P.SelectPreference {
name: "Line Position"
label: qsTr("Spectrum Line Position")
defaultValue: defaultValues["Line Position"]
model: [qsTr("Both"), qsTr("Up"), qsTr("Down")]
}
P.SelectPreference {
name: "Data Length"
label: qsTr("Spectrum Length")
defaultValue: defaultValues["Data Length"]
model: [64, 32, 16, 8]
}
P.SelectPreference {
name: "Channel"
label: qsTr("Channel")
defaultValue: defaultValues["Channel"]
model: [qsTr("Left Channel"), qsTr("Right Channel"), qsTr("Stereo")]
}
P.Separator {}
P.DialogPreference {
name: "Rotate Settings"
label: qsTr("Rotate Settings")
live: true
icon.name: "regular:\uf1de"
P.SwitchPreference {
id: _cfg_preset_line_Rotate_Center_Enable
name: "Center Enable"
label: qsTr("Rotate Center Line")
defaultValue: defaultValues["Rotate Settings"]["Center Enable"]
}
P.SliderPreference {
name: "Center Angle"
label: qsTr("Angle of Center Line")
enabled: _cfg_preset_line_Rotate_Center_Enable.value
from: -45
to: 45
stepSize: 1
defaultValue: defaultValues["Rotate Settings"]["Center Angle"]
displayValue: value + "°"
}
P.Separator {}
P.SwitchPreference {
id: _cfg_preset_line_Rotate_Line_Enable
name: "Line Enable"
label: qsTr("Rotate Spectrum Line")
defaultValue: defaultValues["Rotate Settings"]["Line Enable"]
}
P.SliderPreference {
name: "Line Angle"
label: qsTr("Angle of Spectrum Line")
enabled: _cfg_preset_line_Rotate_Line_Enable.value
from: -75
to: 75
stepSize: 1
defaultValue: defaultValues["Rotate Settings"]["Line Angle"]
displayValue: value + "°"
}
}
P.Separator {}
P.DialogPreference {
name: "Data Settings"
label: qsTr("Data Settings")
live: true
icon.name: "regular:\uf1de"
P.SwitchPreference {
id: _cfg_preset_line_dataSettings_autoNormalizing
name: "Auto Normalizing"
label: qsTr("Auto Normalizing")
defaultValue: defaultValues["Data Settings"]["Auto Normalizing"]
}
P.SpinPreference {
name: "Amplitude"
label: qsTr("Amplitude Ratio")
enabled: !_cfg_preset_line_dataSettings_autoNormalizing.value
message: "1 to 100"
display: P.TextFieldPreference.ExpandLabel
editable: true
from: 1
to: 100
defaultValue: defaultValues["Data Settings"]["Amplitude"]
}
P.Separator {}
P.SelectPreference {
name: "Unit Style"
label: qsTr("Display Style")
defaultValue: defaultValues["Data Settings"]["Unit Style"]
model: [qsTr("Linear"), qsTr("Decibel")]
}
}
}
}

View File

@ -1,140 +1,288 @@
import QtQuick 2.12
import QtQuick 2.12
import QtGraphicalEffects 1.12
import NERvGear.Preferences 1.0 as P
import "../../qml/api"
AdvpStyleTemplate {
style: AdvpCanvasTemplate {
readonly property var audioData: new Array(128)
style: Rectangle {
id: main
width: widget.width;
height: widget.height;
readonly property bool centerLineFlag: configs["Center Line"]
readonly property string center_color: configs["Center Color"]
readonly property string line_color: configs["Line Color"]
readonly property int linePosition: configs["Line Position"]
readonly property int uDataLen: Math.pow(2, configs["Data Length"]);
readonly property int dataLength: 64/uDataLen
readonly property int channel: configs["Channel"]
readonly property bool centerRotateFlag: configs["Rotate Settings"]["Center Enable"]
readonly property real centerRotateAngle: configs["Rotate Settings"]["Center Angle"]*Math.PI/180
readonly property bool lineRotateFlag: configs["Rotate Settings"]["Line Enable"]
readonly property real lineRotateAngle: configs["Rotate Settings"]["Line Angle"]*Math.PI/180
readonly property bool autoNormalizing: configs["Data Settings"]["Auto Normalizing"]
readonly property real amplitude: 400.0/configs["Data Settings"]["Amplitude"]
readonly property int unitStyle: configs["Data Settings"]["Unit Style"]
property bool gradientEnable
property bool centerLineFlag
property string center_color
property real center_width
property int linePosition
property bool vertical_flag
property real _y_dy
property real halfWidth: width/2
property real halfHeight: height/2
readonly property int l_start: (channel===1)*dataLength
readonly property int r_stop: dataLength+dataLength*(channel!==0)
readonly property int total: r_stop-l_start
readonly property real _y_dy: centerRotateFlag*Math.tan(centerRotateAngle)*halfWidth
readonly property real _ux: width/(r_stop-l_start)
readonly property real _dx: Math.round(_ux/2)
onAudioDataUpdeted: {
let normalizing_ratio = autoNormalizing ? data[128] : amplitude;
if (unitStyle) {
//
for(let i=l_start; i<dataLength; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += Math.max(0, 0.4 * (Math.log10(data[63-i*uDataLen-j]/normalizing_ratio)) + 1.0);
}
audioData[i] /= uDataLen;
}
for(let i=dataLength; i<r_stop; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += Math.max(0, 0.4 * (Math.log10(data[i*uDataLen+j]/normalizing_ratio)) + 1.0);
}
audioData[i] /= uDataLen;
}
} else {
//线
for(let i=l_start; i<dataLength; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += data[63-i*uDataLen-j];
}
audioData[i] /= (uDataLen * normalizing_ratio);
}
for(let i=dataLength; i<r_stop; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += data[i*uDataLen+j];
}
audioData[i] /= (uDataLen * normalizing_ratio);
}
LinearGradient {
id: gradient_mask
anchors.fill: parent
visible: gradientEnable
gradient: Gradient {
GradientStop { id: p_start; position: 0.0 }
GradientStop { id: p_middle; position: 0.5 }
GradientStop { id: p_end; position: 1.0 }
}
context.clearRect(0, 0, width+32, height+32);
let _y;
let _dy;
//
if(lineRotateFlag || centerRotateFlag) {
context.transform(1, Math.sin(centerRotateFlag*centerRotateAngle), -Math.sin(lineRotateFlag*lineRotateAngle), 1, Math.sin(lineRotateFlag*lineRotateAngle)*(halfHeight-_y_dy), 0);
context.fillStyle = line_color;
for (let i=l_start; i<r_stop; i++) {
_y = halfHeight*(1-(linePosition!==2)*audioData[i])-_y_dy;
_dy = (halfHeight + (!linePosition)*halfHeight)*audioData[i];
context.fillRect(_ux * (i-l_start), _y, _dx, _dy);
}
if (centerLineFlag) {
context.fillStyle = center_color;
context.fillRect(0, halfHeight-_y_dy, width, 2);
}
context.resetTransform();
} else if (linePosition) {
let _flag = 1-2*(linePosition===1);
_y = halfHeight + halfHeight*(3-2*linePosition)*Boolean(linePosition);
context.fillStyle = line_color;
for (let i=l_start; i<r_stop; i++) {
_dy = height*audioData[i]*_flag;
context.fillRect(_ux * (i-l_start), _y, _dx, _dy);
}
if (centerLineFlag) {
context.fillStyle = center_color;
context.fillRect(0, _y-(2-linePosition)*2, width, 2);
}
} else {
context.fillStyle = line_color;
for (let i=l_start; i<r_stop; i++) {
_y = halfHeight*(1-(linePosition!==2)*audioData[i])-_y_dy;
_dy = (halfHeight + (!linePosition)*halfHeight)*audioData[i];
context.fillRect(_ux * (i-l_start), _y, _dx, _dy);
}
if (centerLineFlag) {
context.fillStyle = center_color;
context.fillRect(0, halfHeight-_y_dy, width, 2);
}
}
context.fill();
requestPaint();
}
Component.onCompleted: {
for (let i = 0; i < 128; i++) {
audioData[i] = 0;
Canvas {
id: centerLine
anchors.fill: parent
contextType: "2d"
renderTarget: Canvas.FramebufferObject
renderStrategy: Canvas.Cooperative
visible: centerLineFlag && !gradientEnable
onPaint: {
context.clearRect(0, 0, width+32, height+32);
context.fillStyle = center_color;
if (vertical_flag) {
if (linePosition) {
let _y = width/2 + width/2*(3-2*linePosition)*Boolean(linePosition);
context.fillRect(_y+(linePosition-2)*center_width, 0, center_width, height);
} else {
context.fillRect(width/2-_y_dy-center_width/2, 0, center_width, width);
}
} else {
if (linePosition) {
let _y = height/2 + height/2*(3-2*linePosition)*Boolean(linePosition);
context.fillRect(0, _y+(linePosition-2)*center_width, width, center_width);
} else {
context.fillRect(0, height/2-_y_dy-center_width/2, width, center_width);
}
}
}
}
layer.enabled: true
layer.effect: OpacityMask{
maskSource: AdvpCanvasTemplate {
readonly property var audioData: new Array(128)
readonly property string line_color: configs["Line Color"]
readonly property int uDataLen: Math.pow(2, configs["Data Length"]);
readonly property int dataLength: 64/uDataLen
readonly property int channel: configs["Channel"]
readonly property bool centerRotateFlag: configs["Rotate Settings"]["Center Enable"]
readonly property real centerRotateAngleTangent: centerRotateFlag*Math.tan(configs["Rotate Settings"]["Center Angle"]*Math.PI/180)
readonly property bool lineRotateFlag: configs["Rotate Settings"]["Line Enable"]
readonly property real lineRotateAngleTangent: lineRotateFlag*Math.tan(configs["Rotate Settings"]["Line Angle"]*Math.PI/180)
readonly property bool autoNormalizing: configs["Data Settings"]["Auto Normalizing"]
readonly property real amplitude: 400.0/configs["Data Settings"]["Amplitude"]
readonly property int unitStyle: configs["Data Settings"]["Unit Style"]
readonly property real xOffset: configs["Rotate Settings"]["X Offset"]/100
readonly property real yOffset: configs["Rotate Settings"]["Y Offset"]/100
readonly property real xScale: configs["Rotate Settings"]["X Scale"]/100
readonly property real yScale: configs["Rotate Settings"]["Y Scale"]/100
readonly property real halfWidth: vertical_flag ? height/2 : width/2
readonly property real halfHeight: vertical_flag ? width/2 : height/2
readonly property int l_start: (channel===1)*dataLength
readonly property int r_stop: dataLength+dataLength*(channel!==0)
readonly property int total: r_stop-l_start
readonly property real _ux: halfWidth*2/(r_stop-l_start)
readonly property real _dx: Math.round(_ux/2)
onWidthChanged: {
if (gradientEnable) {
gradient_mask.end = Qt.point(width*(configs["Gradient Direction"]!==1), height*(configs["Gradient Direction"]%2));
}
centerLine.requestPaint();
}
onHeightChanged: {
if (gradientEnable) {
gradient_mask.start = Qt.point(0, height*(configs["Gradient Direction"]===2));
gradient_mask.end = Qt.point(width*(configs["Gradient Direction"]!==1), height*(configs["Gradient Direction"]%2));
}
centerLine.requestPaint();
}
onConfigsUpdated: {
//使configs使使Qt.callLater(()=>{})
centerLineFlag = configs["Center Line"];
center_color = configs["Center Color"];
center_width = configs["Center Width"]/10;
linePosition = configs["Line Position"];
vertical_flag = configs["Direction"];
gradientEnable = configs["Enable Gradient"];
context.lineWidth = configs["Line Width"];
main.color = configs["Line Color"];
_y_dy = configs["Rotate Settings"]["Center Enable"]*Math.tan(configs["Rotate Settings"]["Center Angle"]*Math.PI/180)*(vertical_flag ? height/2 : width/2);
if (gradientEnable) {
gradient_mask.start = Qt.point(0, height*(configs["Gradient Direction"]===2));
gradient_mask.end = Qt.point(width*(configs["Gradient Direction"]!==1), height*(configs["Gradient Direction"]%2));
p_start.color = configs["Start Position Color"];
p_middle.color = configs["Middle Position Color"];
p_end.color = configs["End Position Color"];
}
centerLine.requestPaint();
}
onAudioDataUpdeted: {
let normalizing_ratio = autoNormalizing ? data[128] : amplitude;
if (unitStyle) {
//
for(let i=l_start; i<dataLength; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += Math.max(0, 0.4 * (Math.log10(data[63-i*uDataLen-j]/normalizing_ratio)) + 1.0);
}
audioData[i] /= uDataLen;
}
for(let i=dataLength; i<r_stop; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += Math.max(0, 0.4 * (Math.log10(data[i*uDataLen+j]/normalizing_ratio)) + 1.0);
}
audioData[i] /= uDataLen;
}
} else {
//线
for(let i=l_start; i<dataLength; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += data[63-i*uDataLen-j];
}
audioData[i] /= (uDataLen * normalizing_ratio);
}
for(let i=dataLength; i<r_stop; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += data[i*uDataLen+j];
}
audioData[i] /= (uDataLen * normalizing_ratio);
}
}
context.clearRect(0, 0, width+32, height+32);
let _y;
let _dy;
if (vertical_flag) {
if(lineRotateFlag || centerRotateFlag) {
context.transform(yScale, lineRotateAngleTangent, -centerRotateAngleTangent, xScale, 2*_y_dy+yOffset*height, xOffset*width-lineRotateAngleTangent*(halfHeight-_y_dy));
context.fillStyle = line_color;
for (let i=l_start; i<r_stop; i++) {
_y = halfHeight*(1-(linePosition!==2)*audioData[i])-_y_dy;
_dy = (halfHeight + (!linePosition)*halfHeight)*audioData[i];
context.fillRect(_y, _ux * (i-l_start), _dy, _dx);
}
if (centerLineFlag) {
context.fillRect(halfHeight-_y_dy-center_width/2, 0, center_width, height);
}
context.resetTransform();
} else if (linePosition) {
let _flag = 1-2*(linePosition===1);
_y = halfHeight + halfHeight*(3-2*linePosition)*Boolean(linePosition);
context.fillStyle = line_color;
for (let i=l_start; i<r_stop; i++) {
_dy = width*audioData[i]*_flag;
context.fillRect(_y, _ux * (i-l_start), _dy, _dx);
}
if (centerLineFlag) {
context.fillRect(_y+(linePosition-2)*center_width, 0, center_width, height);
}
} else {
context.fillStyle = line_color;
for (let i=l_start; i<r_stop; i++) {
_y = halfHeight*(1-(linePosition!==2)*audioData[i])-_y_dy;
_dy = (halfHeight + (!linePosition)*halfHeight)*audioData[i];
context.fillRect(_y, _ux * (i-l_start), _dy, _dx);
}
if (centerLineFlag) {
context.fillRect(halfHeight-_y_dy-center_width/2, 0, center_width, height);
}
}
} else {
//
if(lineRotateFlag || centerRotateFlag) {
context.transform(xScale, centerRotateAngleTangent, -lineRotateAngleTangent, yScale, xOffset*width+lineRotateAngleTangent*(halfHeight-_y_dy), yOffset*height);
context.fillStyle = line_color;
for (let i=l_start; i<r_stop; i++) {
_y = halfHeight*(1-(linePosition!==2)*audioData[i])-_y_dy;
_dy = (halfHeight + (!linePosition)*halfHeight)*audioData[i];
context.fillRect(_ux * (i-l_start), _y, _dx, _dy);
}
if (centerLineFlag) {
context.fillRect(0, halfHeight-_y_dy-center_width/2, width, center_width);
}
context.resetTransform();
} else if (linePosition) {
let _flag = 1-2*(linePosition===1);
_y = halfHeight + halfHeight*(3-2*linePosition)*Boolean(linePosition);
context.fillStyle = line_color;
for (let i=l_start; i<r_stop; i++) {
_dy = height*audioData[i]*_flag;
context.fillRect(_ux * (i-l_start), _y, _dx, _dy);
}
if (centerLineFlag) {
context.fillRect(0, _y+(linePosition-2)*center_width, width, center_width);
}
} else {
context.fillStyle = line_color;
for (let i=l_start; i<r_stop; i++) {
_y = halfHeight*(1-(linePosition!==2)*audioData[i])-_y_dy;
_dy = (halfHeight + (!linePosition)*halfHeight)*audioData[i];
context.fillRect(_ux * (i-l_start), _y, _dx, _dy);
}
if (centerLineFlag) {
context.fillRect(0, halfHeight-_y_dy-center_width/2, width, center_width);
}
}
}
context.fill();
requestPaint();
}
onCompleted: {
for (let i = 0; i < 128; i++) {
audioData[i] = 0;
}
}
onVersionUpdated: {
if (widget.settings.current_style === "nvg://advp.widget.mashiros.top/advp-style-preset/gradient_line") {
widget.settings.current_style = "nvg://advp.widget.mashiros.top/advp-style-preset/line";
widget.settings[widget.settings.current_style] = updateObject(widget.settings["nvg://advp.widget.mashiros.top/advp-style-preset/gradient_line"], widget.settings[widget.settings.current_style]);
widget.settings[widget.settings.current_style]["Enable Gradient"] = true;
}
delete widget.settings[widget.settings.current_style]["Version"];
widget.settings[widget.settings.current_style] = updateObject(defaultValues, widget.settings[widget.settings.current_style]);
}
}
}
}
defaultValues: {
"Version": "1.2.0",
"Version": "1.3.0",
"Enable Gradient": false,
"Gradient Direction": 0,
"Start Position Color": "#f44336",
"Middle Position Color": "#4caf50",
"End Position Color": "#03a9f4",
"Center Line": true,
"Center Color": "#ff4500",
"Center Width": 20,
"Line Color": "#ff4500",
"Line Position": 0,
"Data Length": 0,
"Channel": 2,
"Direction": 0,
"Rotate Settings": {
"Center Enable": false,
"Center Angle": 10,
"Line Enable": false,
"Line Angle": 10
"Line Angle": 10,
"X Scale": 100,
"Y Scale": 100,
"X Offset": 0,
"Y Offset": 0
},
"Data Settings": {
"Auto Normalizing": true,
@ -146,6 +294,44 @@ AdvpStyleTemplate {
preference: AdvpPreference {
version: defaultValues["Version"]
P.SwitchPreference {
id: _cfg_enable_gradient
name: "Enable Gradient"
label: qsTr("Enable Gradient")
defaultValue: defaultValues["Enable Gradient"]
}
P.SelectPreference {
name: "Gradient Direction"
label: qsTr("Gradient Direction")
visible: _cfg_enable_gradient.value
defaultValue: defaultValues["Gradient Direction"]
model: [qsTr("Horizontal"), qsTr("Vertical"), qsTr("Oblique Upward"), qsTr("Oblique downward")]
}
P.ColorPreference {
name: "Start Position Color"
label: qsTr("Start Position Color")
visible: _cfg_enable_gradient.value
defaultValue: defaultValues["Start Position Color"]
}
P.ColorPreference {
name: "Middle Position Color"
label: qsTr("Middle Position Color")
visible: _cfg_enable_gradient.value
defaultValue: defaultValues["Middle Position Color"]
}
P.ColorPreference {
name: "End Position Color"
label: qsTr("End Position Color")
visible: _cfg_enable_gradient.value
defaultValue: defaultValues["End Position Color"]
}
P.Separator {}
P.SwitchPreference {
id: _cfg_preset_line_Center_Line
name: "Center Line"
@ -156,15 +342,35 @@ AdvpStyleTemplate {
P.ColorPreference {
name: "Center Color"
label: qsTr("Center Line Color")
enabled: _cfg_preset_line_Center_Line.value
visible: !_cfg_enable_gradient.value && _cfg_preset_line_Center_Line.value
defaultValue: defaultValues["Center Color"]
}
P.SliderPreference {
name: "Center Width"
label: qsTr("Center Line Width")
visible: _cfg_preset_line_Center_Line.value
from: 1
to: 100
stepSize: 1
defaultValue: defaultValues["Center Width"]
displayValue: value + "%"
}
P.Separator {}
P.SelectPreference {
id: _cfg_direction
name: "Direction"
label: qsTr("Direction")
defaultValue: defaultValues["Direction"]
model: [qsTr("Horizontal"), qsTr("Vertical")]
}
P.ColorPreference {
name: "Line Color"
label: qsTr("Spectrum Line Color")
visible: !_cfg_enable_gradient.value
defaultValue: defaultValues["Line Color"]
}
@ -172,7 +378,7 @@ AdvpStyleTemplate {
name: "Line Position"
label: qsTr("Spectrum Line Position")
defaultValue: defaultValues["Line Position"]
model: [qsTr("Both"), qsTr("Up"), qsTr("Down")]
model: [qsTr("Both"), [qsTr("Up"), qsTr("Left")][_cfg_direction.value], [qsTr("Down"), qsTr("Right")][_cfg_direction.value]]
}
P.SelectPreference {
@ -228,12 +434,58 @@ AdvpStyleTemplate {
name: "Line Angle"
label: qsTr("Angle of Spectrum Line")
enabled: _cfg_preset_line_Rotate_Line_Enable.value
from: -75
to: 75
from: -45
to: 45
stepSize: 1
defaultValue: defaultValues["Rotate Settings"]["Line Angle"]
displayValue: value + "°"
}
P.Separator {}
P.SliderPreference {
name: "X Scale"
label: qsTr("Scale of Center Line Direction")
enabled: _cfg_preset_line_Rotate_Line_Enable.value || _cfg_preset_line_Rotate_Center_Enable.value
from: 1
to: 100
stepSize: 1
defaultValue: defaultValues["Rotate Settings"]["X Scale"]
displayValue: value + "%"
}
P.SliderPreference {
name: "Y Scale"
label: qsTr("Scale of Spectrum Line Direction")
enabled: _cfg_preset_line_Rotate_Line_Enable.value || _cfg_preset_line_Rotate_Center_Enable.value
from: 1
to: 100
stepSize: 1
defaultValue: defaultValues["Rotate Settings"]["Y Scale"]
displayValue: value + "%"
}
P.SliderPreference {
name: "X Offset"
label: qsTr("Offset of Center Line Direction")
enabled: _cfg_preset_line_Rotate_Line_Enable.value || _cfg_preset_line_Rotate_Center_Enable.value
from: -100
to: 100
stepSize: 1
defaultValue: defaultValues["Rotate Settings"]["X Offset"]
displayValue: value + "%"
}
P.SliderPreference {
name: "Y Offset"
label: qsTr("Offset of Spectrum Line Direction")
enabled: _cfg_preset_line_Rotate_Line_Enable.value || _cfg_preset_line_Rotate_Center_Enable.value
from: -100
to: 100
stepSize: 1
defaultValue: defaultValues["Rotate Settings"]["Y Offset"]
displayValue: value + "%"
}
}
P.Separator {}

View File

@ -1,131 +1,201 @@
import QtQuick 2.12
import QtGraphicalEffects 1.12
import NERvGear.Preferences 1.0 as P
import "../../qml/api"
AdvpStyleTemplate {
style: AdvpCanvasTemplate {
readonly property var audioData: new Array(128)
style: Rectangle {
id: main
width: widget.width;
height: widget.height;
//configs
readonly property int linePosition: configs["Line Position"]
readonly property real maxRange: configs["Max Range"] / 100
readonly property int uDataLen: Math.pow(2, configs["Data Length"])
readonly property int dataLength: 64/uDataLen
readonly property int channel: configs["Channel"]
readonly property bool reverse: configs["Reverse"]
readonly property bool rotateFlag: configs["Rotate"]
readonly property real rSpeed: configs["Ratate Speed"] / 100
readonly property real angle: configs["Angle"]
readonly property bool autoNormalizing: configs["Data Settings"]["Auto Normalizing"]
readonly property real amplitude: 400/configs["Data Settings"]["Amplitude"]
readonly property int unitStyle: configs["Data Settings"]["Unit Style"]
property int gradientStyle
readonly property int total: channel*dataLength
readonly property real dotGap: 360/total
property real offsetAngle: 0
property var outerPos: []
property var innerPos: []
readonly property real degUnit: Math.PI/180
readonly property real subRatio: 0.2*maxRange
readonly property real mainRatio: 1-subRatio*2.5
readonly property real minLength: Math.min(width, height)
readonly property real ratio:minLength*subRatio
readonly property real halfWidth: width/2
readonly property real halfHeight: height/2
readonly property real halfMinLength: minLength/2
onConfigsUpdated: {
context.lineWidth = configs["Line Width"];
context.strokeStyle = configs["Main Color"];
}
function createPoint() {
outerPos.length = 0;
innerPos.length = 0;
let deg, deltaR, r1, r2, _rhmLen;
_rhmLen = mainRatio*halfMinLength;
for (let j=0; j < channel; j++) {
for (let i=0; i < dataLength; i++) {
deg = degUnit*((i+j*dataLength)*dotGap + offsetAngle);
deltaR = audioData[reverse*(dataLength-i-1)+(!reverse)*(i+j*dataLength)] * ratio;
r1 = _rhmLen+1+deltaR*(linePosition!==2);
r2 = _rhmLen-1-deltaR*(linePosition!==1);
outerPos.push([halfWidth+Math.cos(deg)*r1,halfHeight+Math.sin(deg)*r1]);
innerPos.push([halfWidth+Math.cos(deg)*r2,halfHeight+Math.sin(deg)*r2]);
}
RadialGradient {
id: radialGradient
anchors.fill: parent
visible: gradientStyle===1
horizontalRadius: Math.min(width, height)/2
verticalRadius: horizontalRadius
gradient: Gradient {
GradientStop {id: radialGradient_pstart}
GradientStop {id: radialGradient_pmiddle}
GradientStop {id: radialGradient_pend}
}
offsetAngle = rotateFlag ? ((offsetAngle + rSpeed) % 360) : angle;
}
onAudioDataUpdeted: {
let normalizing_ratio = autoNormalizing ? data[128] : amplitude;
if (unitStyle) {
//
for(let i=0; i<total; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += Math.max(0, 0.4 * (Math.log10(data[i*uDataLen+j]/normalizing_ratio)) + 1.0);
ConicalGradient {
id: conicalGradient
anchors.fill: parent
visible: gradientStyle===2
angle: -90;
gradient: Gradient {
GradientStop{id: conicalGradient_pstart; position: 0.0}
GradientStop{id: conicalGradient_pquarter; position: 0.25}
GradientStop {id: conicalGradient_phalf; position: 0.5}
GradientStop {id: conicalGradient_p3quarter; position: 0.75}
GradientStop{id: conicalGradient_pend; position: 1.0}
}
}
layer.enabled: true
layer.effect: OpacityMask{
maskSource: AdvpCanvasTemplate {
readonly property var audioData: new Array(128)
//configs
readonly property int linePosition: configs["Line Position"]
readonly property real maxRange: configs["Max Range"] / 100
readonly property int uDataLen: Math.pow(2, configs["Data Length"])
readonly property int dataLength: 64/uDataLen
readonly property int channel: configs["Channel"]
readonly property bool reverse: configs["Reverse"]
readonly property bool rotateFlag: configs["Rotate"]
readonly property real rSpeed: configs["Ratate Speed"] / 100
readonly property real angle: configs["Angle"]
readonly property bool autoNormalizing: configs["Data Settings"]["Auto Normalizing"]
readonly property real amplitude: 400/configs["Data Settings"]["Amplitude"]
readonly property int unitStyle: configs["Data Settings"]["Unit Style"]
readonly property int total: channel*dataLength
readonly property real dotGap: 360/total
property real offsetAngle: 0
property var outerPos: []
property var innerPos: []
readonly property real degUnit: Math.PI/180
readonly property real subRatio: 0.2*maxRange
readonly property real mainRatio: 1-subRatio*2.5
readonly property real minLength: Math.min(width, height)
readonly property real ratio:minLength*subRatio
readonly property real halfWidth: width/2
readonly property real halfHeight: height/2
readonly property real halfMinLength: minLength/2
onConfigsUpdated: {
gradientStyle = configs["Gradient Style"];
context.lineWidth = configs["Line Width"];
main.color = configs["Main Color"];
if (gradientStyle === 1) {
radialGradient_pstart.color = configs["Radial Gradient Settings"]["Inside Position Color"];
radialGradient_pstart.position = configs["Radial Gradient Settings"]["Inside Position"]/100;
radialGradient_pmiddle.color = configs["Radial Gradient Settings"]["Middle Position Color"];
radialGradient_pmiddle.position = configs["Radial Gradient Settings"]["Middle Position"]/100;
radialGradient_pend.color = configs["Radial Gradient Settings"]["Outside Position Color"];
radialGradient_pend.position = configs["Radial Gradient Settings"]["Outside Position"]/100;
} else if (gradientStyle === 2) {
conicalGradient_pstart.color = configs["Conical Gradient Settings"]["Start Position Color"];
conicalGradient_pquarter.color = configs["Conical Gradient Settings"]["Quarter Position Color"];
conicalGradient_phalf.color = configs["Conical Gradient Settings"]["Middle Position Color"];
conicalGradient_p3quarter.color = configs["Conical Gradient Settings"]["End Position Color"];
conicalGradient_pend.color = configs["Conical Gradient Settings"]["Start Position Color"];
}
audioData[i] /= uDataLen;
}
} else {
//线
for(let i=0; i<total; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += data[i*uDataLen+j];
function createPoint() {
outerPos.length = 0;
innerPos.length = 0;
let deg, deltaR, r1, r2, _rhmLen;
_rhmLen = mainRatio*halfMinLength;
for (let j=0; j < channel; j++) {
for (let i=0; i < dataLength; i++) {
deg = degUnit*((i+j*dataLength)*dotGap+offsetAngle);
deltaR = audioData[reverse*(dataLength-i-1)+(!reverse)*(i+j*dataLength)] * ratio;
r1 = _rhmLen+1+deltaR*(linePosition!==2);
r2 = _rhmLen-1-deltaR*(linePosition!==1);
outerPos.push([halfWidth+Math.cos(deg)*r1,halfHeight+Math.sin(deg)*r1]);
innerPos.push([halfWidth+Math.cos(deg)*r2,halfHeight+Math.sin(deg)*r2]);
}
}
audioData[i] /= (uDataLen * normalizing_ratio);
conicalGradient.rotation = offsetAngle;
offsetAngle = rotateFlag ? ((offsetAngle + rSpeed) % 360) : angle;
}
}
context.clearRect(0, 0, width+32, height+32);
createPoint();
onAudioDataUpdeted: {
let normalizing_ratio = autoNormalizing ? data[128] : amplitude;
if (unitStyle) {
//
for(let i=0; i<total; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += Math.max(0, 0.4 * (Math.log10(data[i*uDataLen+j]/normalizing_ratio)) + 1.0);
}
audioData[i] /= uDataLen;
}
} else {
//线
for(let i=0; i<total; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += data[i*uDataLen+j];
}
audioData[i] /= (uDataLen * normalizing_ratio);
}
}
context.beginPath();
context.moveTo(outerPos[0][0], outerPos[0][1]);
for(let i=0; i<total; i++) {
context.lineTo(outerPos[i][0], outerPos[i][1]);
}
context.closePath();
context.stroke();
context.clearRect(0, 0, width+32, height+32);
createPoint();
context.beginPath();
context.moveTo(innerPos[0][0], innerPos[0][1]);
for(let i=0; i<total; i++) {
context.lineTo(innerPos[i][0], innerPos[i][1]);
}
context.closePath();
context.stroke();
context.beginPath();
context.moveTo(outerPos[0][0], outerPos[0][1]);
for(let i=0; i<total; i++) {
context.lineTo(outerPos[i][0], outerPos[i][1]);
}
context.closePath();
context.stroke();
context.beginPath();
for(let i=0; i<total; i++) {
context.moveTo(outerPos[i][0], outerPos[i][1]);
context.lineTo(innerPos[i][0], innerPos[i][1]);
}
context.stroke();
requestPaint();
}
context.beginPath();
context.moveTo(innerPos[0][0], innerPos[0][1]);
for(let i=0; i<total; i++) {
context.lineTo(innerPos[i][0], innerPos[i][1]);
}
context.closePath();
context.stroke();
Component.onCompleted: {
for (let i = 0; i < 128; i++) {
audioData[i] = 0;
context.beginPath();
for(let i=0; i<total; i++) {
context.moveTo(outerPos[i][0], outerPos[i][1]);
context.lineTo(innerPos[i][0], innerPos[i][1]);
}
context.stroke();
requestPaint();
}
onCompleted: {
for (let i = 0; i < 128; i++) {
audioData[i] = 0;
}
}
}
}
}
defaultValues: {
"Version": "1.1.0",
"Version": "1.2.0",
"Gradient Style": 0,
"Radial Gradient Settings": {
"Inside Position Color": "#f44336",
"Middle Position Color": "#4caf50",
"Outside Position Color": "#03a9f4",
"Inside Position": 40,
"Middle Position": 60,
"Outside Position": 80
},
"Conical Gradient Settings": {
"Start Position Color": "#f44336",
"Quarter Position Color": "#4caf50",
"Middle Position Color": "#03a9f4",
"End Position Color": "#ffeb3b"
},
"Main Color": "#ff4500",
"Line Position": 0,
"Line Width": 1,
"Max Range": 50,
"Max Range": 80,
"Data Length": 0,
"Channel": 2,
"Reverse": false,
@ -142,9 +212,107 @@ AdvpStyleTemplate {
preference: AdvpPreference {
version: defaultValues["Version"]
P.SelectPreference {
id: _cfg_gradient_style
name: "Gradient Style"
label: qsTr("Gradient Style")
defaultValue: defaultValues["Gradient Style"]
model: [qsTr("None"), qsTr("Radial Gradient"), qsTr("Conical Gradient")]
}
P.DialogPreference {
name: "Radial Gradient Settings"
label: qsTr("Radial Gradient Settings")
live: true
visible: _cfg_gradient_style.value===1
P.ColorPreference {
name: "Inside Position Color"
label: qsTr("Inside Position Color")
defaultValue: defaultValues["Radial Gradient Settings"]["Inside Position Color"]
}
P.ColorPreference {
name: "Middle Position Color"
label: qsTr("Middle Position Color")
defaultValue: defaultValues["Radial Gradient Settings"]["Middle Position Color"]
}
P.ColorPreference {
name: "Outside Position Color"
label: qsTr("Outside Position Color")
defaultValue: defaultValues["Radial Gradient Settings"]["Outside Position Color"]
}
P.SliderPreference {
id: _cfg_gradient_settings_inside_position
name: "Inside Position"
label: qsTr("Inside Position")
from: 0
to: 75
stepSize: 1
defaultValue: defaultValues["Radial Gradient Settings"]["Inside Position"]
displayValue: value + "%"
}
P.SliderPreference {
id: _cfg_gradient_settings_middle_position
name: "Middle Position"
label: qsTr("Middle Position")
from: _cfg_gradient_settings_inside_position.value + 1
to: 90
stepSize: 1
defaultValue: defaultValues["Radial Gradient Settings"]["Middle Position"]
displayValue: value + "%"
}
P.SliderPreference {
name: "Outside Position"
label: qsTr("Outside Position")
from: _cfg_gradient_settings_middle_position.value + 1
to: 100
stepSize: 1
defaultValue: defaultValues["Radial Gradient Settings"]["Outside Position"]
displayValue: value + "%"
}
}
P.DialogPreference {
name: "Conical Gradient Settings"
label: qsTr("Conical Gradient Settings")
live: true
visible: _cfg_gradient_style.value===2
P.ColorPreference {
name: "Start Position Color"
label: qsTr("Start Position Color")
defaultValue: defaultValues["Conical Gradient Settings"]["Start Position Color"]
}
P.ColorPreference {
name: "Quarter Position Color"
label: qsTr("Quarter Position Color")
defaultValue: defaultValues["Conical Gradient Settings"]["Quarter Position Color"]
}
P.ColorPreference {
name: "Middle Position Color"
label: qsTr("Middle Position Color")
defaultValue: defaultValues["Conical Gradient Settings"]["Middle Position Color"]
}
P.ColorPreference {
name: "End Position Color"
label: qsTr("End Position Color")
defaultValue: defaultValues["Conical Gradient Settings"]["End Position Color"]
}
}
P.ColorPreference {
name: "Main Color"
label: qsTr("Spectrum Line Color")
visible: !_cfg_gradient_style.value
defaultValue: defaultValues["Main Color"]
}
@ -195,8 +363,6 @@ AdvpStyleTemplate {
defaultValue: defaultValues["Channel"]
}
P.Separator {}
P.SwitchPreference {
name: "Reverse"
label: qsTr("Reverse Spectrum")

View File

@ -1,94 +1,179 @@
import QtQuick 2.12
import QtQuick 2.12
import QtGraphicalEffects 1.12
import NERvGear.Preferences 1.0 as P
import "../../qml/api"
AdvpStyleTemplate {
style: AdvpCanvasTemplate {
readonly property var audioData: new Array(128)
style: Rectangle {
id: main
width: widget.width;
height: widget.height;
readonly property bool autoNormalizing: configs["Data Settings"]["Auto Normalizing"]
readonly property real amplitude: 400/configs["Data Settings"]["Amplitude"]
property bool gradientEnable
readonly property int uDataLen: Math.pow(2, configs["Data Length"]);
readonly property int dataLength: 64/uDataLen
readonly property int unitStyle: configs["Data Settings"]["Unit Style"]
readonly property int total: dataLength*2
readonly property real ux: width/(total+1)
readonly property real halfHeight: height/2
onConfigsUpdated: {
//使configs使使Qt.callLater(()=>{})
context.lineWidth = configs["Line Width"];
context.strokeStyle = configs["Line Color"];
LinearGradient {
id: gradient_mask
anchors.fill: parent
visible: gradientEnable
gradient: Gradient {
GradientStop { id: p_start; position: 0.0 }
GradientStop { id: p_middle; position: 0.5 }
GradientStop { id: p_end; position: 1.0 }
}
}
onAudioDataUpdeted: {
let normalizing_ratio = autoNormalizing ? data[128]*2 : amplitude;
if (unitStyle) {
//
for(let i=0; i<dataLength; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += Math.max(0, 0.4 * (Math.log10(data[63-i*uDataLen-j]/normalizing_ratio)) + 1.0);
}
audioData[i] /= uDataLen;
layer.enabled: true
layer.effect: OpacityMask{
maskSource: AdvpCanvasTemplate {
readonly property var audioData: new Array(128)
readonly property bool autoNormalizing: configs["Data Settings"]["Auto Normalizing"]
readonly property real amplitude: 400/configs["Data Settings"]["Amplitude"]
readonly property int uDataLen: Math.pow(2, configs["Data Length"]);
readonly property int dataLength: 64/uDataLen
readonly property int unitStyle: configs["Data Settings"]["Unit Style"]
readonly property int total: dataLength*2
readonly property bool vertical_flag: configs["Direction"]
readonly property real halfWidth: vertical_flag ? height/2 : width/2
readonly property real halfHeight: vertical_flag ? width/2 : height/2
readonly property real ux: halfWidth*2/(total+1)
readonly property real _y_dy: centerRotateAngleTangent*halfWidth
readonly property bool centerRotateFlag: configs["Rotate Settings"]["Center Enable"]
readonly property real centerRotateAngleTangent: centerRotateFlag*Math.tan(configs["Rotate Settings"]["Center Angle"]*Math.PI/180)
readonly property bool lineRotateFlag: configs["Rotate Settings"]["Line Enable"]
readonly property real lineRotateAngleTangent: lineRotateFlag*Math.tan(configs["Rotate Settings"]["Line Angle"]*Math.PI/180)
readonly property real xOffset: configs["Rotate Settings"]["X Offset"]/100
readonly property real yOffset: configs["Rotate Settings"]["Y Offset"]/100
readonly property real xScale: configs["Rotate Settings"]["X Scale"]/100
readonly property real yScale: configs["Rotate Settings"]["Y Scale"]/100
onWidthChanged: {
gradient_mask.end = Qt.point(width*(configs["Gradient Direction"]!==1), height*(configs["Gradient Direction"]%2));
}
for(let i=dataLength; i<total; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += Math.max(0, 0.4 * (Math.log10(data[i*uDataLen+j]/normalizing_ratio)) + 1.0);
}
audioData[i] /= uDataLen;
onHeightChanged: {
gradient_mask.start = Qt.point(0, height*(configs["Gradient Direction"]===2));
gradient_mask.end = Qt.point(width*(configs["Gradient Direction"]!==1), height*(configs["Gradient Direction"]%2));
}
} else {
//线
for(let i=0; i<dataLength; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += data[63-i*uDataLen-j];
onConfigsUpdated: {
//使configs使使Qt.callLater(()=>{})
gradientEnable = configs["Enable Gradient"];
context.lineWidth = configs["Line Width"];
main.color = configs["Line Color"];
if (gradientEnable) {
gradient_mask.start = Qt.point(0, height*(configs["Gradient Direction"]===2));
gradient_mask.end = Qt.point(width*(configs["Gradient Direction"]!==1), height*(configs["Gradient Direction"]%2));
p_start.color = configs["Start Position Color"];
p_middle.color = configs["Middle Position Color"];
p_end.color = configs["End Position Color"];
}
audioData[i] /= (uDataLen * normalizing_ratio);
}
for(let i=dataLength; i<total; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += data[i*uDataLen+j];
onAudioDataUpdeted: {
let normalizing_ratio = autoNormalizing ? data[128]*2 : amplitude;
if (unitStyle) {
//
for(let i=0; i<dataLength; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += Math.max(0, 0.4 * (Math.log10(data[63-i*uDataLen-j]/normalizing_ratio)) + 1.0);
}
audioData[i] /= uDataLen;
}
for(let i=dataLength; i<total; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += Math.max(0, 0.4 * (Math.log10(data[i*uDataLen+j]/normalizing_ratio)) + 1.0);
}
audioData[i] /= uDataLen;
}
} else {
//线
for(let i=0; i<dataLength; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += data[63-i*uDataLen-j];
}
audioData[i] /= (uDataLen * normalizing_ratio);
}
for(let i=dataLength; i<total; i++) {
audioData[i] = 0;
for(let j=0; j<uDataLen; j++) {
audioData[i] += data[i*uDataLen+j];
}
audioData[i] /= (uDataLen * normalizing_ratio);
}
}
audioData[i] /= (uDataLen * normalizing_ratio);
context.clearRect(0, 0, width+32, height+32);
context.beginPath();
context.resetTransform();
if (vertical_flag) {
if (lineRotateFlag || centerRotateFlag) {
context.transform(yScale, lineRotateAngleTangent, -centerRotateAngleTangent, xScale, _y_dy+yOffset*height, xOffset*width-lineRotateAngleTangent*(halfHeight));
}
context.moveTo(halfHeight, 0);
for (let i=0; i<dataLength*2; i+=2) {
context.lineTo(halfHeight*(1+audioData[i]), ux*i);
context.lineTo(halfHeight*(1-audioData[i+1]), ux*(i+1));
}
context.lineTo(halfHeight, height);
} else {
if (lineRotateFlag || centerRotateFlag) {
context.transform(xScale, centerRotateAngleTangent, -lineRotateAngleTangent, yScale, xOffset*width+lineRotateAngleTangent*(halfHeight), yOffset*height-_y_dy);
}
context.moveTo(0, halfHeight);
for (let i=0; i<dataLength*2; i+=2) {
context.lineTo(ux*i, halfHeight*(1+audioData[i]));
context.lineTo(ux*(i+1), halfHeight*(1-audioData[i+1]));
}
context.lineTo(width, halfHeight);
}
context.stroke();
requestPaint();
}
}
context.clearRect(0, 0, width+32, height+32);
context.beginPath();
context.moveTo(0, halfHeight);
for (let i=0; i<dataLength*2; i+=2) {
context.lineTo(ux*i, halfHeight*(1+audioData[i]));
context.lineTo(ux*(i+1), halfHeight*(1-audioData[i+1]));
}
context.lineTo(width, halfHeight);
context.stroke();
requestPaint();
}
Component.onCompleted: {
for (let i = 0; i < 128; i++) {
audioData[i] = 0;
onCompleted: {
for (let i = 0; i < 128; i++) {
audioData[i] = 0;
}
}
}
}
}
defaultValues: {
"Version": "1.1.0",
"Line Width": 1,
"Version": "1.2.0",
"Enable Gradient": false,
"Gradient Direction": 0,
"Start Position Color": "#f44336",
"Middle Position Color": "#4caf50",
"End Position Color": "#03a9f4",
"Line Color": "#ff4500",
"Line Width": 1,
"Data Length": 0,
"Direction": 0,
"Rotate Settings": {
"Center Enable": false,
"Center Angle": 10,
"Line Enable": false,
"Line Angle": 10,
"X Scale": 100,
"Y Scale": 100,
"X Offset": 0,
"Y Offset": 0
},
"Data Settings": {
"Auto Normalizing": true,
"Amplitude": 10,
@ -99,6 +184,58 @@ AdvpStyleTemplate {
preference: AdvpPreference {
version: defaultValues["Version"]
P.SwitchPreference {
id: _cfg_enable_gradient
name: "Enable Gradient"
label: qsTr("Enable Gradient")
defaultValue: defaultValues["Enable Gradient"]
}
P.SelectPreference {
name: "Gradient Direction"
label: qsTr("Gradient Direction")
visible: _cfg_enable_gradient.value
defaultValue: defaultValues["Gradient Direction"]
model: [qsTr("Horizontal"), qsTr("Vertical"), qsTr("Oblique Upward"), qsTr("Oblique downward")]
}
P.ColorPreference {
name: "Start Position Color"
label: qsTr("Start Position Color")
visible: _cfg_enable_gradient.value
defaultValue: defaultValues["Start Position Color"]
}
P.ColorPreference {
name: "Middle Position Color"
label: qsTr("Middle Position Color")
visible: _cfg_enable_gradient.value
defaultValue: defaultValues["Middle Position Color"]
}
P.ColorPreference {
name: "End Position Color"
label: qsTr("End Position Color")
visible: _cfg_enable_gradient.value
defaultValue: defaultValues["End Position Color"]
}
P.Separator {}
P.SelectPreference {
name: "Direction"
label: qsTr("Direction")
defaultValue: defaultValues["Direction"]
model: [qsTr("Horizontal"), qsTr("Vertical")]
}
P.ColorPreference {
name: "Line Color"
label: qsTr("Spectrum Line Color")
visible: !_cfg_enable_gradient.value
defaultValue: defaultValues["Line Color"]
}
P.SliderPreference {
name: "Line Width"
label: qsTr("Spectrum Line Width")
@ -109,14 +246,6 @@ AdvpStyleTemplate {
displayValue: value.toFixed(1) + "px"
}
P.ColorPreference {
name: "Line Color"
label: qsTr("Spectrum Line Color")
defaultValue: defaultValues["Line Color"]
}
P.Separator {}
P.SelectPreference {
name: "Data Length"
label: qsTr("Spectrum Length")
@ -124,6 +253,101 @@ AdvpStyleTemplate {
model: [64, 32, 16, 8]
}
P.Separator {}
P.DialogPreference {
name: "Rotate Settings"
label: qsTr("Rotate Settings")
live: true
icon.name: "regular:\uf1de"
P.SwitchPreference {
id: _cfg_preset_line_Rotate_Center_Enable
name: "Center Enable"
label: qsTr("Rotate Center Line")
defaultValue: defaultValues["Rotate Settings"]["Center Enable"]
}
P.SliderPreference {
name: "Center Angle"
label: qsTr("Angle of Center Line")
enabled: _cfg_preset_line_Rotate_Center_Enable.value
from: -45
to: 45
stepSize: 1
defaultValue: defaultValues["Rotate Settings"]["Center Angle"]
displayValue: value + "°"
}
P.Separator {}
P.SwitchPreference {
id: _cfg_preset_line_Rotate_Line_Enable
name: "Line Enable"
label: qsTr("Rotate Spectrum Line")
defaultValue: defaultValues["Rotate Settings"]["Line Enable"]
}
P.SliderPreference {
name: "Line Angle"
label: qsTr("Angle of Spectrum Line")
enabled: _cfg_preset_line_Rotate_Line_Enable.value
from: -45
to: 45
stepSize: 1
defaultValue: defaultValues["Rotate Settings"]["Line Angle"]
displayValue: value + "°"
}
P.Separator {}
P.SliderPreference {
name: "X Scale"
label: qsTr("Scale of Center Line Direction")
enabled: _cfg_preset_line_Rotate_Line_Enable.value || _cfg_preset_line_Rotate_Center_Enable.value
from: 1
to: 100
stepSize: 1
defaultValue: defaultValues["Rotate Settings"]["X Scale"]
displayValue: value + "%"
}
P.SliderPreference {
name: "Y Scale"
label: qsTr("Scale of Spectrum Line Direction")
enabled: _cfg_preset_line_Rotate_Line_Enable.value || _cfg_preset_line_Rotate_Center_Enable.value
from: 1
to: 100
stepSize: 1
defaultValue: defaultValues["Rotate Settings"]["Y Scale"]
displayValue: value + "%"
}
P.SliderPreference {
name: "X Offset"
label: qsTr("Offset of Center Line Direction")
enabled: _cfg_preset_line_Rotate_Line_Enable.value || _cfg_preset_line_Rotate_Center_Enable.value
from: -100
to: 100
stepSize: 1
defaultValue: defaultValues["Rotate Settings"]["X Offset"]
displayValue: value + "%"
}
P.SliderPreference {
name: "Y Offset"
label: qsTr("Offset of Spectrum Line Direction")
enabled: _cfg_preset_line_Rotate_Line_Enable.value || _cfg_preset_line_Rotate_Center_Enable.value
from: -100
to: 100
stepSize: 1
defaultValue: defaultValues["Rotate Settings"]["Y Offset"]
displayValue: value + "%"
}
}
P.Separator {}
P.DialogPreference {
name: "Data Settings"
label: qsTr("Data Settings")