La Red de Conocimientos Pedagógicos - Conocimientos matemáticos - Dibujar la forma de onda de audio de grabación en iOS

Dibujar la forma de onda de audio de grabación en iOS

Traducción

Gráfico de forma de onda de tira

Gráfico de forma de onda lineal

Configuración de la sesión de audio

Antes de dibujar el gráfico de forma de onda, debe configurar AVAudioSession y crear una matriz. Guardar datos de volumen.

Propiedades relacionadas

RecorderSetting se utiliza para configurar la calidad de grabación y otros datos relacionados.

El temporizador y la frecuencia de actualización se utilizan para actualizar el gráfico de forma de onda periódicamente.

SoundMeter y soundMeterCount se utilizan para guardar la matriz de medidores de volumen.

RecordTime se utiliza para registrar el tiempo de grabación y se puede utilizar para determinar si el tiempo de grabación cumple con los requisitos, etc.

///Grabadora

Grabadora var privada: ¡AVAudioRecorder! ///Configuración de la grabadora de video

Configuración de la grabadora de mensajes privados=[avsampleratekey:ns number(value:float(44100.0)), //Frecuencia de muestreo de sonido.

Avformatidkey: ns número (valor: int 32 (kaudioformatmpg 4 AAC)), //formato de codificación.

Avnumberofchannelskey: ns number (valor: 1), //Recopila pistas de audio.

Clave de calidad de audio de Avencode: número ns (valor: int 32 (calidad de audio. valor medio.raw))]//Calidad de sonido

///Temporizador de grabación

Temporizador var privado: ¿temporizador? ///Intervalo de actualización de forma de onda

Frecuencia de actualización de mensajes privados = 0,05

///Matriz de datos de sonido

Medidores de sonido var privados: [Float]! ///Capacidad de la matriz de datos de sonido

Mensaje privado soundMeterCount = 10

///Tiempo de grabación

Tiempo de grabación de var privado = 0,00

Configuración relacionada con la sesión de audio

Configurar AVAudioSession se utiliza para configurar avaudiosession, donde AVAudioSessionCategoryRecord significa que solo se graba esta sesión. Si se requiere reproducción, se puede configurar en avaudiesessioncategoryplayandrerecord o AvaudieSessionCategoryplayBlack. La diferencia entre los dos es que uno puede grabar y reproducir, y el otro puede reproducir en segundo plano (es decir, la voz aún se puede reproducir después de silenciarla).

ConfigRecord se utiliza para configurar todo AVAudioRecoder, incluida la adquisición de permisos, la configuración de fuente de proxy, si se deben grabar tablas de volúmenes, etc.

DirectoryURL es la dirección donde se guarda el archivo de configuración.

configuración de función privadaAVAudioSession(){ let session = avaudiosession . instancia compartida()do { try session . set Category(avaudiosessioncategoryplayandrerecord, with: .defaultToSpeaker) } catch { print("Error en la configuración de la sesión")}

}

registro de configuración de función privada(){ avaudiosession instancia compartida().

requestRecordPermission {(permitir)

si! permitir {return

}

} let session = avaudiosession . instancia compartida()do { try session . configuración fallida ")} hacer { self . recorder = probar AVAudioRecorder(URL:self . directorio yurl()!, configuración:self . recorder settings)self . recorder . delegado = self

self . recorder . preparetorecord ()self . recorder . ismeteringenabled = true

} catch { print(error . descripción localizada)

} do { prueba avaudiosession(). setActive(true) } catch { print("Error en la actividad de la sesión")}

}

URL del directorio de funciones privadas()-& gt; { //Hacer algo...

Devolver la URL del archivo de sonido

}

Grabar datos de audio

Después de grabar, usamos El temporizador que acaba de configurar obtiene continuamente la potencia promedio y la guarda en una matriz.

El temporizador llama a UpdateMeters y los datos de volumen grabados en la grabadora se guardan continuamente en la matriz soundMeter.

AddSoundMeter se utiliza para agregar datos.

Contador de actualización de función privada(){

recorder.updateMeters()

Tiempo de grabación += frecuencia de actualización

añadir sonómetro(elemento :recorder potencia promedio(para canal:0))

}

función privada agregar sonómetro(elemento:Float){ si los sonómetros cuentan & lt;soundMeterCount {

.

soundMeters.append(item)

} else { for (index, _)in sonómetros enumerados(){ if index <soundMeterCount - 1 {

SoundMeter Sounder[ index] = sounder[index + 1]

}

}//Insertar nuevos datos

soundMeters[soundMeterCount-1]= centro de notificación de elementos predeterminado. post(name: NSNotification. Name.init("updateMeters "), objeto: soundMeters)

}

}

Empiece a dibujar formas de onda

Ahora que tenemos todos los datos que necesitamos, podemos comenzar a dibujar el gráfico de forma de onda. En este momento nos situamos en el archivo MCVolumeView.swift.

En el paso anterior, enviamos una notificación llamada updateMeters para notificar a MCVolumeView que actualice el gráfico de forma de onda.

Anular init(frame:CG rect){ super . init(frame:frame)

backgroundColor = UIColor.clear

Content-mode =. ¿Repintar? // El modo de contenido se vuelve a dibujar porque es necesario volver a dibujar la tabla de volúmenes muchas veces.

centro de notificaciones. valor predeterminado. agregar observador(self, selector:# selector(vista de actualización(aviso:)), nombre: NSNotification. Name.init("updateMeters "), objeto: nil)

}

@ vista de actualización de función privada de objc(aviso:Notificación){

soundMeters = aviso.objeto como! [Flotante]

setNeedsDisplay()

}

Al llamar a setNeedsDisplay, se llamará al método drawRect, donde podemos dibujar formas de onda.

NoVoice y maxVolume se utilizan para garantizar el rango de visualización del sonido.

El gráfico de forma de onda se dibuja mediante CGContext y, por supuesto, también se puede dibujar mediante UIBezierPath.

Anular función draw(_ rect:CG rect){ if soundMeters! =cero& amp& ampsoundMeters.count & gt0 { let contexto = UIGraphicsGetCurrentContext()

¿Contexto? . setLineCap(.circle)

¿Contexto? . setLineJoin(.circle)

¿Contexto? . setStrokeColor(ui color . white . CG color)

Establecer noVoice = -46.0 //Este valor significa que todos los sonidos por debajo de -46.0 se consideran silenciosos.

Establezca maxVolume = 55.0 //Este valor representa el sonido máximo como 55.0.

//Dibujar volumen...

¿Contexto? . StrokePath()

}

}

Dibujo de un gráfico de forma de onda en columnas

Calcule la altura de cada columna según maxVolume y noVoice, y mueve el contexto Dibuja el punto donde se encuentra.

También cabe señalar que los puntos de coordenadas en CGContext están invertidos, por lo que se requiere el eje de coordenadas inverso para el cálculo.

Keith. bar:?

¿Contexto? . establecerAnchoDeLínea(3)? para (índice, elemento) en la tabla fonética. Enumeración(){ let bar height = max volume-(double(item)-no voice)//Calcule la altura del medidor de voz que debe mostrarse a través del medidor de voz actual.

¿Contexto? . mover(a:CGPoint(x: índice * 6 + 3, y: 40))

¿Contexto? . addLine(to: CGPoint(x: index * 6 + 3, y: Int(barHeight)))

}

Dibujo de un gráfico de forma de onda lineal

" La "altura" se calcula de la misma manera que una franja, pero cuando se dibuja una forma de onda de franja, la línea se dibuja primero y luego se mueve, mientras que cuando se dibuja una forma de onda de franja, la línea se mueve primero y luego se dibuja.

Keith. Línea:

¿Contexto? .

Establezca el ancho de línea (1,5) para (índice, elemento) en sonómetros. Enumeración(){ let position = volumen máximo-(double(item)-no voice)//Calcule la altura del segmento de línea correspondiente.

¿Contexto? . addLine(to:CG point(x:Double(index * 6+3), y: posición))

¿Contexto? . Move(to: CGPoint(x: Double(index * 6 + 3), y: position))

}

}

Mejorar aún más nuestra imagen de forma de onda .

En muchos casos, la grabación no solo necesita mostrar el gráfico de forma de onda, sino que también requiere que mostremos el tiempo y el progreso de la grabación actual, por lo que podemos agregar una barra de progreso de grabación al gráfico de forma de onda, así que giramos al archivo MCProgressView.swift.

Utiliza UIBezierPath para dibujar con CAShapeLayer.

MaskPath es la máscara de toda la ruta de progreso. Debido a que nuestro HUD de grabación no es un cuadrado normal, es necesario cortarlo con la ruta de progreso de la máscara.

ProgressPath es la ruta de progreso y el progreso se dibuja de izquierda a derecha.

La animación es la animación del dibujo de la ruta de progreso.

configuración de función privada animate(){ let mask path = UIBezierPath(rect redondeado:CG rect . init(x: 0, y: 0, ancho: frame.width, alto: frame.height), esquina radio:HUDCornerRadius)let capa de máscara = CAShapeLayer()

color de fondo de la máscara = color de interfaz de usuario claro

maskLayer.path = maskPath.cgPath

<. p>maskLayer.frame = límites

//Ruta de progreso

/*

El centro de la ruta es el centro del HUD y el ancho es la altura del HUD, comenzando desde la izquierda Dibuja hacia la derecha.

*/

let ProgressPath = CGMutablePath()

ruta de progreso. mover(a:punto CG(x:0,y: frame.height / 2) ))

ruta de progreso. addline(a:punto CG(x: marco. ancho, y: marco. altura / 2))

progressLayer = CAShapeLayer()

progressLayer.frame = límites

capa de progreso color de relleno = uicolor.clear.cgcolor//Color de fondo de la capa.

color de trazo de capa de progreso = color de interfaz de usuario (rojo: 0,29, verde: 0,29, azul: 0,29, alfa: 0,90).

cgColor? //Color de dibujo de capa

capa de progreso. límite de línea = kCALineCapButt

ancho de línea de progreso = altura del hud

ruta de capa de progreso = ruta de progreso

. p>

progressLayer.mask = maskLayer

animation = cabasic Animation(keyPath:" final del trazo ")

Animation.duration = 60 //Duración máxima de grabación

p>

Animación. Función de sincronización = función de sincronización camedia (nombre: kcamediating funcional lineal) // viajando a velocidad constante.

modo de relleno de animación = kCAFillModeForwards

animación.fromValue = 0.0

animación.toValue = 1.0

animación.autoreverses = false

animation.repeatCount = 1

}

Etiqueta

Las anteriores son algunas de mis experiencias y opiniones al dibujar formas de onda de grabación. En la demostración, también agregué sombras y desenfoque gaussiano al HUD de grabación para darle más textura en la pantalla, así que lo omitiré. Aun así, creo que este HUD de grabación todavía tiene algunos defectos. Primero, el acoplamiento con VC es relativamente alto. En segundo lugar, el efecto de dibujar gráficos de formas de onda lineales no es razonable. Si hay una manera mejor, espero que puedas comunicarte conmigo.