Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@
/.node_modules.ember-try/
/bower.json.ember-try
/package.json.ember-try

# capacitor build files
/ios/
/android/
/electron/
/.gradle*
63 changes: 48 additions & 15 deletions app/components/audio-capturer.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,60 @@
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { Plugins } from '@capacitor/core';
const { VoiceRecorder, Device, Filesystem } = Plugins;
import { File } from '@ionic-native/file';
import { Media } from '@ionic-native/media';

export default class AudioCapturerComponent extends Component {
@action
async startRecording() {
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: false
});
const options = { mimeType: 'audio/webm' };
this.mediaRecorder = new MediaRecorder(stream, options);

this.mediaRecorder.addEventListener('dataavailable', e => {
this.args.uploadAudioVideo({ blob: e.data });
});

this.mediaRecorder.start();
const deviceInfo = await Device.getInfo();

if (deviceInfo.operatingSystem === 'ios') {
const canRecord = await VoiceRecorder.canDeviceVoiceRecord();
if (canRecord) {
const permissionGranted = await VoiceRecorder.requestAudioRecordingPermission();
if (permissionGranted) {
const fileName = `${Date.now()}_wuf_audio_recording.m4a`;
await File.createFile(File.tempDirectory, fileName, true);
this.file = Media.create(File.tempDirectory.replace(/^file:\/\//, '') + fileName);
this.file.startRecord();
}
}
} else {
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: false
});
const options = { mimeType: 'audio/webm' };
this.mediaRecorder = new MediaRecorder(stream, options);

this.mediaRecorder.addEventListener('dataavailable', e => {
this.args.uploadAudioVideo({ blob: e.data });
});

this.mediaRecorder.start();
}
}

@action
stopRecording() {
if (this.mediaRecorder) {
this.mediaRecorder.stop();
async stopRecording() {
const deviceInfo = await Device.getInfo();

if (deviceInfo.operatingSystem === 'ios') {
this.file.stopRecord();

const { data } = await Filesystem.readFile({
path: `file://${this.file._objectInstance.src}`,
});
const buffer = Uint8Array.from(window.atob(data), c => c.charCodeAt(0)).buffer;
const blob = new Blob([buffer], { type : 'audio/m4a' });

this.args.uploadAudioVideo(blob);
} else {
if (this.mediaRecorder) {
this.mediaRecorder.stop();
}
}
}
}
2 changes: 1 addition & 1 deletion app/components/bark-type.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<div class="flex h-full items-center justify-center w-full">
{{#animated-if @barkType use=this.fade duration=1000}}
<div class="mr-4">
{{svg-jar @barkType height="200" width="200"}}
{{svg-jar @barkType class="h-48 max-w-sm w-full"}}
</div>
<div class="flex-grow">
<h2 class="font-bold text-3xl">
Expand Down
2 changes: 1 addition & 1 deletion app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Wuf</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do? I haven't used it before.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is part of what allows the app to respect the safeareas of the notch in an iPhone X or 11.


{{content-for "head"}}

Expand Down
31 changes: 22 additions & 9 deletions app/services/audio-analyzer.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
determineBarkType,
getTimeDomainMaxMin
} from 'wuf/utils/barks';
import { Plugins } from '@capacitor/core';
const { Device } = Plugins;

const barkDescriptions = {
alert:
Expand All @@ -33,7 +35,7 @@ export default class AudioAnalyzerService extends Service {
@action
async analyseAudio(buffer) {
// 44100 hz is the sample rate equivalent to CD audio
const offline = new OfflineAudioContext(2, buffer.length, 44100);
const offline = new (window.OfflineAudioContext || window.webkitOfflineAudioContext)(2, buffer.length, 44100);
const bufferSource = offline.createBufferSource();
bufferSource.onended = () => {
this.barkType = determineBarkType(this.barksOccurred, this.pitches);
Expand All @@ -51,7 +53,7 @@ export default class AudioAnalyzerService extends Service {
this.amplitudeArray = new Uint8Array(analyser.frequencyBinCount);
// The buckets of the array range from 0-22050 Hz, with each bucket representing ~345 Hz
this.frequencyArray = new Uint8Array(analyser.frequencyBinCount);

scp.onaudioprocess = () => {
analyser.getByteTimeDomainData(this.amplitudeArray);
analyser.getByteFrequencyData(this.frequencyArray);
Expand Down Expand Up @@ -123,15 +125,26 @@ export default class AudioAnalyzerService extends Service {
* @param {*} file
*/
@action
async uploadAudioVideo(file) {
async uploadAudioVideo(data) {
this.clearBarkData();
this.clearCanvas();
const fileReader = new FileReader();
fileReader.onload = async ev => {
this.audioContext = new AudioContext();
const buffer = await this.audioContext.decodeAudioData(ev.target.result);
const deviceInfo = await Device.getInfo();

if (deviceInfo.operatingSystem === 'ios') {
const fileReader = new FileReader();
fileReader.onload = async ev => {
const audioContext = new window.webkitAudioContext();

audioContext.decodeAudioData(ev.target.result, (buffer) => {
this.analyseAudio(buffer);
});
};
return fileReader.readAsArrayBuffer(data);
} else {
const audioContext = new AudioContext();
const arrayBuffer = await data.blob.arrayBuffer();
const buffer = await audioContext.decodeAudioData(arrayBuffer);
this.analyseAudio(buffer);
};
return fileReader.readAsArrayBuffer(file.blob);
}
}
}
2 changes: 2 additions & 0 deletions app/styles/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
body {
@apply text-main;
font-family: 'Poppins', sans-serif;
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
}

.animated-container {
Expand Down
2 changes: 1 addition & 1 deletion app/templates/microphone.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</h2>

<div class="flex justify-center">
{{svg-jar "bath" class="h-auto max-w-sm w-full"}}
{{svg-jar "bath" class="h-64 md:h-auto max-w-sm w-full"}}
</div>

<AudioCapturer
Expand Down
2 changes: 1 addition & 1 deletion app/templates/upload.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</h2>

<div class="flex justify-center">
{{svg-jar "house" class="h-auto max-w-sm w-full"}}
{{svg-jar "house" class="h-64 md:h-auto max-w-sm w-full"}}
</div>

<AudioUploader
Expand Down
20 changes: 20 additions & 0 deletions capacitor.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"appId": "com.example.app",
"appName": "ember-capacitor-app",
"bundledWebRuntime": false,
"npmClient": "yarn",
"webDir": "dist",
"server": {
"url": "http://localhost:4200",
"allowNavigation": [
"example.org",
"*.example.org"
]
},
"plugins": {
"SplashScreen": {
"launchShowDuration": 0
}
},
"cordova": {}
}
13 changes: 13 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
},
"devDependencies": {
"@babel/plugin-proposal-object-rest-spread": "^7.8.3",
"@capacitor/cli": "^2.2.0",
"@capacitor/core": "^2.2.0",
"@ember/optional-features": "^1.3.0",
"@glimmer/component": "^1.0.0",
"@glimmer/tracking": "^1.0.0",
Expand All @@ -29,6 +31,7 @@
"ember-cli": "~3.16.0",
"ember-cli-app-version": "^3.2.0",
"ember-cli-babel": "^7.17.2",
"ember-cli-capacitor": "^0.0.4",
"ember-cli-dependency-checker": "^3.2.0",
"ember-cli-eslint": "^5.1.0",
"ember-cli-fastboot": "^2.2.1",
Expand Down Expand Up @@ -67,5 +70,15 @@
},
"ember": {
"edition": "octane"
},
"dependencies": {
"@capacitor/android": "2.2.0",
"@capacitor/ios": "2.2.0",
"@ionic-native/core": "^5.27.0",
"@ionic-native/file": "^5.27.0",
"@ionic-native/media": "^5.27.0",
"capacitor-voice-recorder": "^0.0.91",
"cordova-plugin-file": "^6.0.2",
"cordova-plugin-media": "^5.0.3"
}
}
Loading