Skip to content

Commit

Permalink
Merge pull request #95 from DeveloperAcademy-POSTECH/bug/#94-CantFind…
Browse files Browse the repository at this point in the history
…AudiofileAfterUpdate

[bugfix] #94 - 업데이트 시 url 변경으로 인한 음원 파일 못 가져와 억양 계산 안되는 현상 해결
  • Loading branch information
SSub-jun authored Nov 30, 2024
2 parents 71e2a80 + 16797d7 commit 5fa73af
Showing 1 changed file with 82 additions and 55 deletions.
137 changes: 82 additions & 55 deletions PepperoniV2/Presentation/Helper/SpeechGrader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,69 +78,96 @@ private func levenshteinDistance(_ source: String, _ target: String) -> Int {

// calculateIntonation 함수
func calculateIntonation(referenceFileName: String, comparisonFileURL: URL) -> Double {
let referenceURL = URL(fileURLWithPath: referenceFileName)

// 파일 존재 여부 확인
guard FileManager.default.fileExists(atPath: referenceURL.path) else {
print("참조 파일을 찾을 수 없습니다: \(referenceURL.path)")
return 0.0
}
guard let referencePitchData = extractPitchData(from: referenceURL, applyVolumeThreshold: false), // 볼륨 기준 미적용
let comparisonPitchData = extractPitchData(from: comparisonFileURL, applyVolumeThreshold: true) else { // 볼륨 기준 적용
print("피치 데이터를 추출할 수 없습니다.")
return 0.0
}

// 이후 코드는 동일
let validReferenceData = referencePitchData.compactMap { $0 > 0 ? $0 : nil }
let validComparisonData = comparisonPitchData.compactMap { $0 > 0 ? $0 : nil }

guard !validReferenceData.isEmpty, !validComparisonData.isEmpty else {
print("유효한 피치 데이터가 부족합니다.")
return 0.0
var referenceURL: URL?

// Documents 이하 경로 추출
if let documentRange = referenceFileName.range(of: "/Documents/") {
let relativePath = String(referenceFileName[documentRange.upperBound...]) // "CHOIAE_008.m4a"

// 현재 앱의 Document 디렉토리 경로 가져오기
let currentDocumentDirectory = FileManager.default
.urls(for: .documentDirectory, in: .userDomainMask)[0]

// 새로운 URL 생성
referenceURL = currentDocumentDirectory.appendingPathComponent(relativePath)

print("Updated URL: \(referenceURL)") // /var/mobile/Containers/Data/Application/NEW_UUID/Documents/CHOIAE_008.m4a
} else {
print("Invalid path: \(referenceFileName)")
}

let resampledComparisonData = resamplePitchData(source: validComparisonData, targetLength: validReferenceData.count)
let referenceMean = validReferenceData.reduce(0, +) / CGFloat(validReferenceData.count)
let comparisonMean = resampledComparisonData.reduce(0, +) / CGFloat(resampledComparisonData.count)
let normalizedReferenceData = validReferenceData.map { $0 - referenceMean }
let normalizedComparisonData = resampledComparisonData.map { $0 - comparisonMean }

var matchingStates = 0
for i in 1..<validReferenceData.count {
let referenceDiff = normalizedReferenceData[i] - normalizedReferenceData[i - 1]
let comparisonDiff = normalizedComparisonData[i] - normalizedComparisonData[i - 1]
if let referenceURL = referenceURL {

// 파일 존재 여부 확인
guard FileManager.default.fileExists(atPath: referenceURL.path) else {
print("참조 파일을 찾을 수 없습니다: \(referenceURL.path)")
return 0.0
}
guard let referencePitchData = extractPitchData(from: referenceURL, applyVolumeThreshold: false), // 볼륨 기준 미적용
let comparisonPitchData = extractPitchData(from: comparisonFileURL, applyVolumeThreshold: true) else { // 볼륨 기준 적용
print("피치 데이터를 추출할 수 없습니다.")
return 0.0
}

let referenceState = referenceDiff > 0 ? 1 : (referenceDiff < 0 ? -1 : 0)
let comparisonState = comparisonDiff > 0 ? 1 : (comparisonDiff < 0 ? -1 : 0)
// 이후 코드는 동일
let validReferenceData = referencePitchData.compactMap { $0 > 0 ? $0 : nil }
let validComparisonData = comparisonPitchData.compactMap { $0 > 0 ? $0 : nil }

if referenceState == comparisonState {
matchingStates += 1
guard !validReferenceData.isEmpty, !validComparisonData.isEmpty else {
print("유효한 피치 데이터가 부족합니다.")
return 0.0
}

let resampledComparisonData = resamplePitchData(source: validComparisonData, targetLength: validReferenceData.count)
let referenceMean = validReferenceData.reduce(0, +) / CGFloat(validReferenceData.count)
let comparisonMean = resampledComparisonData.reduce(0, +) / CGFloat(resampledComparisonData.count)
let normalizedReferenceData = validReferenceData.map { $0 - referenceMean }
let normalizedComparisonData = resampledComparisonData.map { $0 - comparisonMean }

var matchingStates = 0
for i in 1..<validReferenceData.count {
let referenceDiff = normalizedReferenceData[i] - normalizedReferenceData[i - 1]
let comparisonDiff = normalizedComparisonData[i] - normalizedComparisonData[i - 1]

let referenceState = referenceDiff > 0 ? 1 : (referenceDiff < 0 ? -1 : 0)
let comparisonState = comparisonDiff > 0 ? 1 : (comparisonDiff < 0 ? -1 : 0)

if referenceState == comparisonState {
matchingStates += 1
}
}

let similarity = Double(matchingStates) / Double(validReferenceData.count - 1)
let intonationScore = similarity * 100
let referenceLength = Double(validReferenceData.count)
let comparisonLength = Double(validComparisonData.count)
let lengthScore = max(0.0, 100.0 * (min(comparisonLength, referenceLength) / max(comparisonLength, referenceLength)))

let score = (intonationScore * 0.7) + (lengthScore * 0.3)
let finalScore: Double
switch similarity {
case 0.55...1.0:
finalScore = Double(90 + (similarity - 0.55) / 0.15 * 10)
case 0.45..<0.55:
finalScore = Double(75 + (similarity - 0.45) / 0.10 * 15)
case 0.30..<0.45:
finalScore = Double(50 + (similarity - 0.30) / 0.15 * 25)
case 0.0..<0.30:
finalScore = Double(similarity / 0.30 * 50)
default:
finalScore = 0
}

return min(100.0, finalScore)

} else {

print("Error: referenceURL is not valid")
return 0

}

let similarity = Double(matchingStates) / Double(validReferenceData.count - 1)
let intonationScore = similarity * 100
let referenceLength = Double(validReferenceData.count)
let comparisonLength = Double(validComparisonData.count)
let lengthScore = max(0.0, 100.0 * (min(comparisonLength, referenceLength) / max(comparisonLength, referenceLength)))

let score = (intonationScore * 0.7) + (lengthScore * 0.3)
let finalScore: Double
switch similarity {
case 0.55...1.0:
finalScore = Double(90 + (similarity - 0.55) / 0.15 * 10)
case 0.45..<0.55:
finalScore = Double(75 + (similarity - 0.45) / 0.10 * 15)
case 0.30..<0.45:
finalScore = Double(50 + (similarity - 0.30) / 0.15 * 25)
case 0.0..<0.30:
finalScore = Double(similarity / 0.30 * 50)
default:
finalScore = 0
}

return min(100.0, finalScore)
}


Expand Down

0 comments on commit 5fa73af

Please sign in to comment.