2017-09-20 2 views
0

발표해야 나는 또한 updateCurrentValue로 업데이트 UILabel 모든 숫자의 값을 얻을, 나는 999 int의 같은 번호 (000 ~ 999)를 한 그들은 모두 UILabel에 인쇄되어 있습니다 나는 발표 function을 수행하는 UIButton을 누르면, 수 (15) (예를 들어) 발표에 대한 AVFoundation하고 코드를 통해 각을 가져 숫자의 소리 것은 :스위프트 : 멀티 기능 문제

지금
if currentValue == 15 { 
Sound15?.play() 
} 

내가 코드를 찾고 있어요 그 왜냐하면 999 개의 숫자 모두에 대해 function을 만드는 것은 시간 낭비 일 것이기 때문입니다. 어떤 방법으로도 value 만 제공 할 수 있으며 나머지 숫자는 자동으로 func을 찾습니다. 나는 누군가가 대답 할 수 있도록 충분히 분명하게 할 수 있기를 바란다. 여기에 내가 지금까지 가지고있는 것이 있습니다 :

import UIKit 
import AVFoundation 

class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate { 

var Sound1:AVAudioPlayer? 
var Sound2:AVAudioPlayer? 
var Sound3:AVAudioPlayer? 
var Sound4:AVAudioPlayer? 
var Sound5:AVAudioPlayer? 
var Sound6:AVAudioPlayer? 
var Sound7:AVAudioPlayer? 
var Sound8:AVAudioPlayer? 
var Sound9:AVAudioPlayer? 
var Sound10:AVAudioPlayer? 
var Sound11:AVAudioPlayer? 
var Sound12:AVAudioPlayer? 
var Sound13:AVAudioPlayer? 
var Sound14:AVAudioPlayer? 
var Sound15:AVAudioPlayer? 
var Sound16:AVAudioPlayer? 
var Sound17:AVAudioPlayer? 
var Sound18:AVAudioPlayer? 
var Sound19:AVAudioPlayer? 
var Sound20:AVAudioPlayer? 
var Sound30:AVAudioPlayer? 
var Sound40:AVAudioPlayer? 
var Sound50:AVAudioPlayer? 
var Sound60:AVAudioPlayer? 
var Sound70:AVAudioPlayer? 
var Sound80:AVAudioPlayer? 
var Sound90:AVAudioPlayer? 
var Sound100:AVAudioPlayer? 
var Sound200:AVAudioPlayer? 
var Sound300:AVAudioPlayer? 
var Sound400:AVAudioPlayer? 
var Sound500:AVAudioPlayer? 
var Sound600:AVAudioPlayer? 
var Sound700:AVAudioPlayer? 
var Sound800:AVAudioPlayer? 
var Sound900:AVAudioPlayer? 

var currentValue = 0 

func updateCurrentValue() { 
    let hundreds = max(0, pickerView.selectedRow(inComponent: 0)) 
    let tens = max(0, pickerView.selectedRow(inComponent: 1)) 
    let ones = max(0, pickerView.selectedRow(inComponent: 2)) 

    currentValue = hundreds * 100 + tens * 10 + ones 
} 

func numberOfComponents(in pickerView: UIPickerView) -> Int { 
    return 3 
} 

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { 
    return String(row) 
} 

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { 
return 10 // digits 0 - 9 
} 

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { 
    updateCurrentValue() 

    changeLabelText() 
} 

//Some Functions as example of how it works: 

private func accouncingNumbers() { 

//for single digit 

if currentValue == 1 { 
Sound1?.play() 
} 

//for double digits 

if currentValue == 24 { 
Sound20?.play() 
SoundTimer = Timer.scheduledTimer(withTimeInterval: 1.2, repeats: false) {timer in 
    self.Sound4?.play() 
    self.SoundTimer?.invalidate() 
    self.SoundTimer = nil 
} 
} 

//for 3-digits 

if currentValue == 146 { 
Sound100?.play() 
SoundTimer = Timer.scheduledTimer(withTimeInterval: 1.2, repeats: false) {timer in 
    self.Sound40?.play() 
    self.SoundTimer?.invalidate() 
    self.SoundTimer = nil 
    self.SoundTimer = Timer.scheduledTimer(withTimeInterval: 1.2, repeats: false) {timer in 
     self.Sound6?.play() 
     self.SoundTimer?.invalidate() 
     self.SoundTimer = nil 
    } 
} 
} 

//Sounds imported here 

    do 

    { 
    let audioURL1 = Bundle.main.url(forResource: "1", withExtension: "mp3")! 
    Sound1 = try AVAudioPlayer(contentsOf: audioURL1) 
    Sound1?.prepareToPlay() 


    } 


    catch 

    { 
    print(error) 
    } 

} 

이 과정에서 더 쉽고 간단한 방법을 찾으려고합니다.

func verbalizeValue(_ value: Int) { 
    let announcements = prepareAnnouncements(value) 
    playAnnouncements(announcements) 
} 

func prepareAnnouncements(_ value: Int) -> [String] { 
    var valueToProcess: Int = value 
    var announcements: [String] = [] 
    if valueToProcess >= 100 { 
     // values 100 and above 
     let hundred = valueToProcess/100 
     valueToProcess = valueToProcess % 100 
     let soundfile = "say_\(hundred)00.wav" 
     announcements.append(soundfile) 
    } 
    if valueToProcess >= 20 { 
     // values 30 to 99 
     let dozen = valueToProcess/10 
     valueToProcess = valueToProcess % 10 
     let soundfile = "say_\(dozen)0.wav" 
     announcements.append(soundfile) 
    } 
    if valueToProcess > 1 || announcements.count == 0 { 
     // values 0 to 19 
     let soundfile = "say_\(value).wav" 
     announcements.append(soundfile) 
    } 
    return announcements 
} 

func playAnnouncements(_ announcements: [String]) { 
    // announcements contains an array of wave filenames to play one after the other 
} 

그런 다음 당신이 다시로드 하나의 AVAudioPlayer을 사용할 수 있습니다 : 당신이 당신의 응용 프로그램에 번들 할 필요가 사운드 파일의 양을 최소화하기 위해

+2

왜 오디오 플레이어가 2 대 이상입니까? – rmaddy

+0

오디오 플레이어가 생성되고 설정되는 방법을 보여주는 코드를 업데이트하여 수행중인 작업을 볼 수 있습니다. – rmaddy

+0

이 방금 코드를 업데이트했습니다. @rmaddy – Shahin

답변

3

, 당신이 유사한 알고리즘을 원할 것입니다 적절한 웨이브 파일, 재생 시작, 현재 사운드 재생 완료, 대기열에있는 다음 웨이브 파일로드 및 대기열이 비어있을 때까지 재생. 요구 사항에 따라 재생을 중단하고 녹음 메시지 대기열을 플러시 할 수 있습니다.

또는 지원되는 범위의 모든 숫자에 웨이브 파일을 사용할 수 있으며 say_0.mp3에서 say_999로 간단하게 번호를 매길 수 있습니다. mp3; 버튼을 누를 때 콘솔 로그에서

// 
// ViewController.swift 
// SayNumber 
// 
// Created by Dave Poirier on 2017-09-21. 
// Copyright © 2017 Soft.io. All rights reserved. 
// 

import UIKit 
import AVFoundation 

class ViewController: UIViewController, AVAudioPlayerDelegate { 

    var valueToAnnonce: Int = 321 
    var audioPlayer: AVAudioPlayer! 
    var audioQueue: [String] = [] 

    @IBAction 
    func announceValue(_ sender: Any?) { 
     verbalizeValue(valueToAnnonce) 
    } 

    func verbalizeValue(_ value: Int) { 
     let announcements = prepareAnnouncements(value) 
     playAnnouncements(announcements) 
    } 

    func prepareAnnouncements(_ value: Int) -> [String] { 
     var valueToProcess: Int = value 
     var announcements: [String] = [] 
     if valueToProcess >= 100 { 
      // values 100 and above 
      let hundred = valueToProcess/100 
      valueToProcess = valueToProcess % 100 
      let soundfile = "say_\(hundred)00" 
      announcements.append(soundfile) 
     } 
     if valueToProcess >= 20 { 
      // values 30 to 99 
      let dozen = valueToProcess/10 
      valueToProcess = valueToProcess % 10 
      let soundfile = "say_\(dozen)0" 
      announcements.append(soundfile) 
     } 
     if valueToProcess >= 1 || announcements.count == 0 { 
      // values 0 to 19 
      let soundfile = "say_\(valueToProcess)" 
      announcements.append(soundfile) 
     } 
     return announcements 
    } 

    func playAnnouncements(_ announcements: [String]) { 
     // announcements contains an array of wave filenames to play one after the other 
     if nil != audioPlayer && audioPlayer!.isPlaying { 
      print("Audio player was active, stop it and play the new announcements!") 
      audioPlayer.stop() 
     } 
     audioQueue.removeAll() 
     for filename in announcements { 
      let path = pathForAudioFile(filename) 
      if path != nil { 
       audioQueue.append(path!) 
      } 
     } 
     playNextInQueue() 
    } 

    func playNextInQueue() { 
     let nextPathInQueue = audioQueue.first 
     if nextPathInQueue != nil { 
      audioQueue.removeFirst(1) 
      let audioFileURL = URL(fileURLWithPath: nextPathInQueue!) 
      audioPlayer = try? AVAudioPlayer(contentsOf: audioFileURL) 
      guard audioPlayer != nil else { 
       print("Oops, file not found: \(nextPathInQueue!)") 
       return 
      } 
      print("playing \(nextPathInQueue!)") 
      audioPlayer?.delegate = self 
      audioPlayer?.play() 
     } else { 
      print("looks like we are all done!") 
     } 
    } 

    func pathForAudioFile(_ filename: String) -> String? { 
     return Bundle.main.path(forResource: filename, ofType: "wav") 
    } 

    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { 
     DispatchQueue.main.async { 
      self.playNextInQueue() 
     } 
    } 
} 

: 당신이 더 큰 숫자 (100 만 3 백 75688)

여기 완전 작업 예제를 지원하는 시작하면 정말 지루한 도착 다음은 볼 수 있습니다 :

playing /var/containers/Bundle/Application/E2D5E7AD-26B4-4BBA-B52C-B91B62BA7161/SayNumber.app/say_300.wav 
playing /var/containers/Bundle/Application/E2D5E7AD-26B4-4BBA-B52C-B91B62BA7161/SayNumber.app/say_20.wav 
playing /var/containers/Bundle/Application/E2D5E7AD-26B4-4BBA-B52C-B91B62BA7161/SayNumber.app/say_1.wav 
looks like we are all done! 

컨트롤러는 오디오 파일 say_900하는 say_100.wav에서 수백 다음, say_90.wav하는 say_20.wav에서 모든 다스에 대한 다음, say_19.wav을 통해 같은 say_0.wav 기대하고있다. wav. 코드는 어떤 길이의 번호에도 쉽게 적용 할 수 있어야합니다.

+3

@ekscrypto가 말한 (투표 한) 것에 덧붙여,'AVAudioPlayer'는 델리게이트 속성을 가지고 있습니다. 만약 당신이 델리게이트로 만들고'audioPlayerDidFinishPlaying (_ : successfully :)'함수를 구현한다면, 새로운 사운드를 트리거 할 수 있습니다. 타이머를 만드는 것보다 이전의 사운드가 완료되었습니다. –

+0

불행히도이 알고리즘을 사용하는 방법에 익숙하지 않습니다. 아나운서 함수의 UIButton + UIButton이 어떻게 작동하는지 (내 코드에 따라) 설정하면 멋질 것입니다. @ekscrypto – Shahin

+0

@Shahin 학교 임무가 아니길 바래요. – ekscrypto