Просмотр исходного кода

音乐品质质量等级功能的实现

onecold 1 год назад
Родитель
Сommit
ee6d609443

+ 72 - 1
entry/src/main/ets/common/util/Utility.ets

@@ -945,6 +945,10 @@ export class Utility {
             videoItem.lyricContent  = tags.LYRICS || tags.lyrics  ||  tags.USLT || tags.UNSYNCEDLYRICS || '';
             videoItem.genre  = tags.genre||tags.GENRE|| Utility.resourceToString(context, $r('app.string.unknown'));
             videoItem.track  = tags.track||tags.TRACK|| Utility.resourceToString(context, $r('app.string.unknown'));
+
+            if(sampleRate&&format.bit_rate){
+              videoItem.md5Str = determineAudioQuality( videoItem.mimeType,Number(format.bit_rate),Number(sampleRate))
+            }
             // 检查是否有封面图片流
             const hasCover = metadata.streams.some(stream  =>
             stream.disposition?.attached_pic  === 1
@@ -1800,4 +1804,71 @@ function formatBitrateToKbps(bitRate: string, decimalPlaces: number = 0): string
 
   // 3. 格式化输出
   return `${kbps.toFixed(decimalPlaces)}  kbps`;
-}
+}
+
+
+// 定义音质等级
+enum AudioQuality {
+  LQ = "LQ",             // 低音质
+  SQ = "SQ",             // 标准音质
+  HQ = "HQ",             // 高音质
+  LOSSLESS = "Lossless", // 无损
+  HIRES = "Hi-Res"       // 高解析度
+}
+
+// 明确定义支持的音频格式类型
+interface SupportedFormats {
+  LOSSY: Set<string>;
+  LOSSLESS: Set<string>;
+}
+
+// 声明并初始化支持的音频格式(符合类型定义)
+const SUPPORTED_FORMATS: SupportedFormats = {
+  LOSSY: new Set(['mp3', 'aac', 'ogg', 'opus', 'wma']),
+  LOSSLESS: new Set(['flac', 'alac', 'ape', 'wav', 'aiff'])
+};
+
+/**
+ * 根据音频参数判断音质等级
+ * @param format 编码格式(字符串,不区分大小写,如"MP3"或"flac")
+ * @param bitrate 比特率(单位:bps,如320kbps需传入320000)
+ * @param sampleRate 采样率(单位:Hz,如44.1kHz需传入44100)
+ * @param bitDepth 位深(单位:bit,默认16bit,Hi-Res需≥24bit)
+ * @returns AudioQuality 音质等级
+ */
+function determineAudioQuality(
+  format: string,
+  bitrate: number,
+  sampleRate: number
+): AudioQuality {
+  // 统一转为小写便于比较
+  const normalizedFormat = format.toLowerCase();
+
+  // --------------- 第一步:判断是否无损/Hi-Res ---------------
+  const isLossless = SUPPORTED_FORMATS.LOSSLESS.has(normalizedFormat);
+  if (isLossless) {
+    // Hi-Res标准:采样率≥96kHz且位深≥24bit
+    if (sampleRate >= 96000 ) {
+      return AudioQuality.HIRES;
+    }
+    // CD级无损标准:采样率≥44.1kHz且位深≥16bit
+    if (sampleRate >= 44100) {
+      return AudioQuality.LOSSLESS;
+    }
+  }
+
+  // --------------- 第二步:有损音质判断 ---------------
+  // 高音质标准:比特率≥256kbps且采样率≥44.1kHz
+  if (bitrate >= 256000 && sampleRate >= 44100) {
+    return AudioQuality.HQ;
+  }
+  // 标准音质:比特率≥128kbps且采样率≥22.05kHz
+  else if (bitrate >= 128000 && sampleRate >= 22050) {
+    return AudioQuality.SQ;
+  }
+  // 其余情况为低音质
+  else {
+    return AudioQuality.LQ;
+  }
+}
+

+ 5 - 1
entry/src/main/ets/pages/SplashIndex.ets

@@ -384,10 +384,14 @@ struct  SplashIndex{
                 params:{ titleName:'ICP备案',webUrl:CommonConstants.ICP_URL}
               });
             })
-          Text(this.appName)
+          Text('无损音乐播放器')
             .fontColor(Color.Grey)
             .fontSize(18)
             .margin({top:20})
+          // Text(this.appName)
+          //   .fontColor(Color.Grey)
+          //   .fontSize(18)
+          //   .margin({top:20})
           Text(CommonConstants.ICP_NO)
             .fontColor(Color.Grey)
             .fontSize(9)

+ 54 - 11
entry/src/main/ets/view/LocalMusic.ets

@@ -2566,6 +2566,19 @@ export struct LocalMusic {
                 })
               )
             Row() {
+              Column(){
+                Text(item.md5Str?.includes('Lossless')?
+                   Utility.resourceToString(this.context,$r('app.string.lossless')):item.md5Str)//音质
+                  .fontSize(this.twoFingerType == 1 ? 8 : this.twoFingerType == 2 ? 9 : 11)
+                  .padding({ top: 3,right:6,left:6,bottom:3 })
+                  .fontColor(this.currentSong?.filePath === item.filePath ? this.themeColor :
+                  $r('app.color.text_color'))
+                  .fontWeight(500)
+                  .borderRadius(12)
+                  .margin({ left: this.twoFingerType == 3 ? 6 : 8 })
+                  .backgroundColor('#FFC107')
+              }
+              .padding({ top: 8 })
               Text(StrUtil.isEmpty(item.artist) ? item.cTime : item.artist + '  ' + item?.album)
                 .fontSize(this.twoFingerType == 1 ? 11 : this.twoFingerType == 2 ? 12 : 14)
                 .padding({ top: 8 })
@@ -3600,17 +3613,34 @@ export struct LocalMusic {
                 .fontSize(this.twoFingerType == 1 ? 10 : this.twoFingerType == 2 ? 12 : 14)
                 .visibility(this.modeType === 3 && !this.isCanBack ? Visibility.Visible : Visibility.None)
                 .fontColor($r('app.color.text_color'))
-              Text(StrUtil.isEmpty(item.artist) ? 'Unknown' : item.artist)
-                .fontSize(11)
-                .fontSize(this.twoFingerType == 1 ? 10 : this.twoFingerType == 2 ? 12 : 14)
-                .maxLines(1)
-                .margin({ top: 2 })
-                .visibility(item.type == CommonConstants.TYPE_IS_ARTIST
-                  || item.type == CommonConstants.TYPE_IS_ALBUM
-                  || item.type == CommonConstants.TYPE_IS_DIR ? Visibility.None : Visibility.Visible)
-                .fontWeight(FontWeight.Medium)
-                .fontColor(this.currentSong?.filePath === item.filePath ? this.themeColor :
-                $r('app.color.text_color'))
+              Row(){
+                Column(){
+                  Text(item.md5Str?.includes('Lossless')?
+                  Utility.resourceToString(this.context,$r('app.string.lossless')):item.md5Str)//音质
+                    .fontSize(this.twoFingerType == 1 ? 8 : this.twoFingerType == 2 ? 9 : 11)
+                    .padding({ top: 3,right:6,left:6,bottom:3 })
+                    .fontColor(this.currentSong?.filePath === item.filePath ? this.themeColor :
+                    $r('app.color.text_color'))
+                    .fontWeight(500)
+                    .borderRadius(12)
+                    .margin({ left: this.twoFingerType == 3 ? 6 : 8 })
+                    .backgroundColor('#FFC107')
+                }
+                .margin({ top: 2 ,right:6})
+                Text(StrUtil.isEmpty(item.artist) ? 'Unknown' : item.artist)
+                  .fontSize(11)
+                  .fontSize(this.twoFingerType == 1 ? 10 : this.twoFingerType == 2 ? 12 : 14)
+                  .maxLines(1)
+                  .textOverflow({ overflow: TextOverflow.MARQUEE })//超长滚动
+                  .margin({ top: 2 ,right:18})
+                  .visibility(item.type == CommonConstants.TYPE_IS_ARTIST
+                    || item.type == CommonConstants.TYPE_IS_ALBUM
+                    || item.type == CommonConstants.TYPE_IS_DIR ? Visibility.None : Visibility.Visible)
+                  .fontWeight(FontWeight.Medium)
+                  .fontColor(this.currentSong?.filePath === item.filePath ? this.themeColor :
+                  $r('app.color.text_color'))
+              }
+
 
             }
             .alignItems(HorizontalAlign.Center) // 关键:使内容水平居中
@@ -5684,6 +5714,19 @@ export struct LocalMusic {
               .maxLines(1)
               .margin({ left: this.twoFingerType == 3 ? 18 : 10 })
             Row() {
+              Column(){
+                Text(item.md5Str?.includes('Lossless')?
+                Utility.resourceToString(this.context,$r('app.string.lossless')):item.md5Str)//音质
+                  .fontSize(this.twoFingerType == 1 ? 8 : this.twoFingerType == 2 ? 9 : 11)
+                  .padding({ top: 3,right:6,left:6,bottom:3 })
+                  .fontColor(this.currentSong?.filePath === item.filePath ? this.themeColor :
+                  $r('app.color.text_color'))
+                  .fontWeight(500)
+                  .borderRadius(12)
+                  .margin({ left: this.twoFingerType == 3 ? 6 : 8 })
+                  .backgroundColor('#FFC107')
+              }
+              .padding({ top: 8 })
               Text(StrUtil.isEmpty(item.artist) ? item.cTime : item.artist + '  ' + item?.album)
                 .fontSize(this.twoFingerType == 1 ? 11 : this.twoFingerType == 2 ? 12 : 14)
                 .padding({ top: 8 })

+ 4 - 0
entry/src/main/resources/base/element/string.json

@@ -455,6 +455,10 @@
     {
       "name": "unknown",
       "value": "unknown"
+    },
+    {
+      "name": "lossless",
+      "value": "Lossless"
     }
   ]
 }

+ 4 - 0
entry/src/main/resources/zh_CN/element/string.json

@@ -204,6 +204,10 @@
     {
       "name": "unknown",
       "value": "未知"
+    },
+    {
+      "name": "lossless",
+      "value": "无损"
     }
   ]
 }