├── README.md
├── VoiceFilter.ipynb
├── assets
├── audio_samples
│ ├── sample_1
│ │ ├── clean_1.flac
│ │ ├── noise_1.flac
│ │ └── target_1.flac
│ └── sample_2
│ │ ├── clean_2.flac
│ │ ├── noise_2.flac
│ │ └── target_2.flac
└── images
│ ├── app.png
│ ├── dev_sdr.png
│ ├── loss.png
│ ├── model_plot.png
│ ├── model_workflow.PNG
│ └── system_arch.PNG
├── configuration
├── Audio.py
└── HyperParams.py
├── dataset
├── dataset_creation.py
├── directory_structure.py
├── preload_training_dataset.py
└── speech_collection.py
├── flutter app
└── voicefilter
│ ├── .gitignore
│ ├── README.md
│ ├── android
│ ├── .gitignore
│ ├── app
│ │ ├── build.gradle
│ │ └── src
│ │ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── voicefilter
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── res
│ │ │ │ ├── drawable
│ │ │ │ └── launch_background.xml
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ └── values
│ │ │ │ └── styles.xml
│ │ │ └── profile
│ │ │ └── AndroidManifest.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ └── settings.gradle
│ ├── assets
│ ├── audio1.png
│ ├── audio2.png
│ └── audio3.png
│ ├── fonts
│ ├── Montserrat-Regular.ttf
│ ├── Poppins-Regular.ttf
│ ├── Raleway-Regular.ttf
│ └── Spartan-Regular.ttf
│ ├── ios
│ ├── .gitignore
│ ├── Flutter
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.xcconfig
│ │ └── Release.xcconfig
│ ├── Runner.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── WorkspaceSettings.xcsettings
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── Runner
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ ├── Icon-App-20x20@1x.png
│ │ │ ├── Icon-App-20x20@2x.png
│ │ │ ├── Icon-App-20x20@3x.png
│ │ │ ├── Icon-App-29x29@1x.png
│ │ │ ├── Icon-App-29x29@2x.png
│ │ │ ├── Icon-App-29x29@3x.png
│ │ │ ├── Icon-App-40x40@1x.png
│ │ │ ├── Icon-App-40x40@2x.png
│ │ │ ├── Icon-App-40x40@3x.png
│ │ │ ├── Icon-App-60x60@2x.png
│ │ │ ├── Icon-App-60x60@3x.png
│ │ │ ├── Icon-App-76x76@1x.png
│ │ │ ├── Icon-App-76x76@2x.png
│ │ │ └── Icon-App-83.5x83.5@2x.png
│ │ └── LaunchImage.imageset
│ │ │ ├── Contents.json
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ └── README.md
│ │ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ │ ├── Info.plist
│ │ └── Runner-Bridging-Header.h
│ ├── lib
│ ├── main.dart
│ ├── screens
│ │ ├── embedding_screen.dart
│ │ ├── filter_screen.dart
│ │ └── login_register_screen.dart
│ ├── services
│ │ ├── api.dart
│ │ ├── auth_manager.dart
│ │ └── auth_service.dart
│ ├── utilities
│ │ └── constants.dart
│ └── widgets
│ │ ├── custom_painter.dart
│ │ ├── dialogbox.dart
│ │ └── player_widget.dart
│ ├── pubspec.yaml
│ └── test
│ └── widget_test.dart
├── model
├── model.py
└── sequence_generator.py
├── requirements.txt
└── train_test
├── testing.py
└── train.py
/README.md:
--------------------------------------------------------------------------------
1 | # Voice Filter
2 |
3 | This is a Tensorflow/Keras implementation of Google AI VoiceFilter.
4 |
5 | Our work is inspired from the the academic paper : https://arxiv.org/abs/1810.04826
6 |
7 | The implementation is based on the work : https://github.com/mindslab-ai/voicefilter
8 |
9 | ---
10 |
11 | ### Team Members
12 |
13 | 1. [Angshuman Saikia](https://github.com/HeliosX7)
14 |
15 | 1. [Abhinav Jain](https://github.com/jain-abhinav02)
16 |
17 | 1. [Yashwardhan Gautam](https://github.com/yashwardhan-gautam)
18 |
19 | ---
20 |
21 | ### Introduction
22 | We intend to improve the accuracy of Automatic speech recognition(ASR) by separating the speech of the primary speaker.
23 | This project has immense application in chatbots, voice assistants, video conferencing.
24 |
25 | ---
26 |
27 | ### Who is our primary speaker ?
28 | All users of a service will have to record their voice print during enrolment. The voice print associated with the account is used to identify the primary speaker.
29 |
30 | ### How is voice print recorded ?
31 | A audio clip is processed by a separately trained deep neural network to generate a speaker discriminative embedding. As a result, all speakers are represented by a vector of length 256.
32 |
33 | ---
34 |
35 | ### How to prepare Dataset ?
36 | We use the publicly available speech dataset - Librispeech. We select a primary and secondary speaker at random. For the primary speaker, select a random speech for reference and a random speech for input. Select a random speech of the secondary speaker. The input speeches of primary and secondary users are mixed which serves as one of the input. The reference speech is passed through a pre trained model ( Source: https://github.com/mindslab-ai/voicefilter ) to create an embedding which serves as the other input. The output is the input speech of the primary speaker.
37 | The speeches are not used directly. Instead, they are converted into magnitude spectrogram before being fed into a deep neural network. We have used python's librosa library to perform all audio related functions.
38 |
39 | We created a dataset of 29351 samples that have been divided into 8 parts for ease of use with limited RAM.
40 | Link to the kaggle dataset: https://www.kaggle.com/abhinavjain02/speech-separation
41 |
42 | ---
43 |
44 | ### Stats on Prepared Data
45 |
46 | It took around 11 hours to prepare the dataset on Google Colab. The code is present in the [dataset](/dataset) folder.
47 |
48 | > Note: All ordered pairs of primary and secondary speakers are unique
49 |
50 | | Stat/Dataset | Train | Dev | Test |
51 | |:----------------------------:|:-------------:|:-------------:|:----------:|
52 | | Total no. of unique speeches available in LibriSpeech Dataset | 28539 | 2703 | 2620 |
53 | | No. of unique speeches used | 26869 | 1878 | 1838 |
54 | | Percentage of total speeches used | 94.15 % | 69.48 % | 70.15 % |
55 | | Total no. of samples prepared | 29351 | 934 | 964 |
56 | | No. of samples with same primary and reference speech | 376 (1.28 %) | 10 (1.07 %) | 11 (1.14 %) |
57 |
58 | ---
59 |
60 | ### Proposed System Architecture
61 |
62 |
63 |
64 | ---
65 |
66 | ### Requirements
67 |
68 | * This code was tested on Python 3.6.9 with [Google Colab](colab.research.google.com).
69 |
70 | Other packages can be installed by:
71 |
72 | ```
73 | pip install -r requirements.txt
74 | ```
75 |
76 |
77 | ### Model
78 |
79 |
80 |
81 | ---
82 |
83 | The model architecture is precisely as per the academic paper mentioned above. The model takes a input spectrogram and d vector(embedding) as input and produces a soft mask which when superimposed on the input spectrogram produces the output spectrogram. The output spectrogram is combined with the input phase to re create the primary speakers audio from the mixed input speech.
84 |
85 |
86 | | Loss Function | Optimizer | Metrics |
87 | |:--------------------:|:------------------:|:-------------:|
88 | | Mean Squared Error (MSE) | adam | Sound to Distortion Ratio(SDR) |
89 |
90 | ---
91 |
92 |
93 |
94 | ---
95 |
96 | ### Training
97 |
98 | * The model was trained on Google Colab for 30 epochs.
99 | * Training took about 37 hours on NVIDIA Tesla P100 GPU.
100 |
101 | ### Results
102 |
103 | * Loss
104 |
105 |
106 |
107 | * Validation SDR
108 |
109 |
110 |
111 | * Test
112 |
113 | > Note: The following results are based on model weights after 29th epoch( Peak SDR on validation )
114 |
115 | | Loss | SDR |
116 | |:-------------:|:------------:|
117 | | 0.0104 | 5.3250 |
118 |
119 | ---
120 |
121 | ### Audio Samples
122 |
123 | * Listen to the sample audio from the [assets/audio_samples](/assets/audio_samples) folder.
124 |
125 | ---
126 |
127 | ### Key learnings:
128 |
129 | * Processing Audio data using [librosa](https://github.com/librosa/librosa)
130 | * Creating flexible architechtures using [Keras functional API](https://keras.io/guides/functional_api/)
131 | * Using custom generator in keras
132 | * Using custom callbacks in keras
133 | * Multi-Processing in python
134 |
135 | ---
136 |
137 | ### App Snippet
138 |
139 |
140 |
--------------------------------------------------------------------------------
/assets/audio_samples/sample_1/clean_1.flac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/audio_samples/sample_1/clean_1.flac
--------------------------------------------------------------------------------
/assets/audio_samples/sample_1/noise_1.flac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/audio_samples/sample_1/noise_1.flac
--------------------------------------------------------------------------------
/assets/audio_samples/sample_1/target_1.flac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/audio_samples/sample_1/target_1.flac
--------------------------------------------------------------------------------
/assets/audio_samples/sample_2/clean_2.flac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/audio_samples/sample_2/clean_2.flac
--------------------------------------------------------------------------------
/assets/audio_samples/sample_2/noise_2.flac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/audio_samples/sample_2/noise_2.flac
--------------------------------------------------------------------------------
/assets/audio_samples/sample_2/target_2.flac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/audio_samples/sample_2/target_2.flac
--------------------------------------------------------------------------------
/assets/images/app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/images/app.png
--------------------------------------------------------------------------------
/assets/images/dev_sdr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/images/dev_sdr.png
--------------------------------------------------------------------------------
/assets/images/loss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/images/loss.png
--------------------------------------------------------------------------------
/assets/images/model_plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/images/model_plot.png
--------------------------------------------------------------------------------
/assets/images/model_workflow.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/images/model_workflow.PNG
--------------------------------------------------------------------------------
/assets/images/system_arch.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/assets/images/system_arch.PNG
--------------------------------------------------------------------------------
/configuration/Audio.py:
--------------------------------------------------------------------------------
1 | import librosa
2 | import numpy as np
3 |
4 | class Audio:
5 | def __init__(self,hyper_params):
6 | self.hyper_params = hyper_params
7 | self.mel_basis_matrix = librosa.filters.mel(sr=hyper_params.sample_rate,
8 | n_fft=hyper_params.n_fft,
9 | n_mels=hyper_params.embedder_num_mels)
10 |
11 | def get_mel_spec(self,wave):
12 | spec = librosa.core.stft(y=wave, n_fft=self.hyper_params.n_fft,
13 | hop_length=self.hyper_params.hop_length,
14 | win_length=self.hyper_params.win_length,
15 | window='hann')
16 | power_spec = np.abs(spec) ** 2
17 | mel_spec = np.log10(np.dot(self.mel_basis_matrix,power_spec)+1e-6)
18 | return mel_spec
19 | def wave2spec(self,wave):
20 | spec = librosa.core.stft(y=wave, n_fft=self.hyper_params.n_fft,
21 | hop_length=self.hyper_params.hop_length,
22 | win_length=self.hyper_params.win_length)
23 | phase = np.angle(spec)
24 | spec_db = self.amp2db(np.abs(spec))
25 | spec_db_norm = self.normalize(spec_db)
26 | spec_db_norm = spec_db_norm.T # Taking transpose here
27 | phase = phase.T # Taking transpose here
28 | return spec_db_norm, phase
29 | def spec2wave(self,spec_db_norm,phase):
30 | spec_db_norm, phase = spec_db_norm.T, phase.T
31 | spec_db = self.denormalize(spec_db_norm)
32 | spec_amp = self.db2amp(spec_db)
33 | spec = spec_amp * np.exp(1j*phase)
34 | wave = librosa.core.istft(spec,
35 | hop_length=self.hyper_params.hop_length,
36 | win_length=self.hyper_params.win_length)
37 | return wave
38 | def amp2db(self,mat):
39 | return 20.0 * np.log10(np.maximum(1e-5,mat)) - self.hyper_params.ref_level_db
40 | def db2amp(self,mat):
41 | return np.power(10.0, (mat+self.hyper_params.ref_level_db)*0.05)
42 | def normalize(self,mat):
43 | return np.clip((mat-self.hyper_params.min_level_db)/-self.hyper_params.min_level_db, 0.0 , 1.0)
44 | def denormalize(self, mat):
45 | return np.clip(mat,0.0,1.0)*(-self.hyper_params.min_level_db)+self.hyper_params.min_level_db
--------------------------------------------------------------------------------
/configuration/HyperParams.py:
--------------------------------------------------------------------------------
1 | class HyperParams:
2 | n_fft= 1200
3 | num_freq= 601 # n_fft//2 + 1
4 | sample_rate= 16000
5 | hop_length= 160
6 | win_length= 400
7 | min_level_db= -100.0
8 | ref_level_db= 20.0
9 | preemphasis= 0.97
10 | power= 0.30
11 | embedder_window= 80
12 | data_audio_len= 3.0
13 | embedder_num_mels= 40
14 | embedder_lstm_hidden = 768
15 | embedder_emb_dim = 256
16 | embedder_lstm_layers = 3
17 | embedder_window = 80
18 | embedder_stride = 40
19 | model_lstm_dim = 400
20 | model_fc1_dim = 600
21 | model_fc2_dim = 601 # num_freq
--------------------------------------------------------------------------------
/dataset/dataset_creation.py:
--------------------------------------------------------------------------------
1 | import os
2 | import pickle
3 | import torch
4 | import torch.nn as nn
5 | import random
6 | import pandas as pd
7 | import time
8 | import numpy as np
9 | import librosa
10 | from multiprocessing import Pool
11 | from Audio import Audio
12 | from HyperParams import HyperParams
13 |
14 | class LinearNorm(nn.Module):
15 | def __init__(self, hp):
16 | super(LinearNorm, self).__init__()
17 | self.linear_layer = nn.Linear(hp.embedder_lstm_hidden, hp.embedder_emb_dim)
18 |
19 | def forward(self, x):
20 | return self.linear_layer(x)
21 |
22 | class SpeechEmbedder(nn.Module):
23 | def __init__(self, hp):
24 | super(SpeechEmbedder, self).__init__()
25 | self.lstm = nn.LSTM(hp.embedder_num_mels,
26 | hp.embedder_lstm_hidden,
27 | num_layers=hp.embedder_lstm_layers,
28 | batch_first=True)
29 | self.proj = LinearNorm(hp)
30 | self.hp = hp
31 |
32 | def forward(self, mel):
33 | # (num_mels, T)
34 | mels = mel.unfold(1, self.hp.embedder_window, self.hp.embedder_stride) # (num_mels, T', window)
35 | mels = mels.permute(1, 2, 0) # (T', window, num_mels)
36 | x, _ = self.lstm(mels) # (T', window, lstm_hidden)
37 | x = x[:, -1, :] # (T', lstm_hidden), use last frame only
38 | x = self.proj(x) # (T', emb_dim)
39 | x = x / torch.norm(x, p=2, dim=1, keepdim=True) # (T', emb_dim)
40 | x = x.sum(0) / x.size(0) # (emb_dim), average pooling over time frames
41 | return x
42 |
43 | def get_dvector(wave):
44 | mel_spec = audio.get_mel_spec(wave)
45 | dvec = embedder(torch.from_numpy(mel_spec).float())
46 | dvec = dvec.detach().numpy()
47 | return dvec
48 |
49 | def create_example(target_dir, hyper_params, idx, ref_speech, pri_speech, sec_speech):
50 | sample_rate = hyper_params.sample_rate
51 | ref_wave, _ = librosa.load(ref_speech,sr=sample_rate) #load the audio file
52 | pri_wave, _ = librosa.load(pri_speech, sr = sample_rate)
53 | sec_wave,_ = librosa.load(sec_speech, sr = sample_rate)
54 | assert len(ref_wave.shape)==len(pri_wave.shape)==len(sec_wave.shape)==1,\
55 | 'wave files must be mono and not stereo'
56 | ref_wave,_ = librosa.effects.trim(ref_wave, top_db = 20) # clip silent portion on both ends
57 | pri_wave,_ = librosa.effects.trim(pri_wave, top_db = 20)
58 | sec_wave,_ = librosa.effects.trim(sec_wave, top_db = 20)
59 |
60 | if ref_wave.shape[0] < 1.1 * hyper_params.embedder_window * hyper_params.hop_length :
61 | return
62 | length_wave = int(sample_rate * hyper_params.data_audio_len)
63 | if pri_wave.shape[0] 0:
105 | diff_mod = n1 - diff_mod
106 | ref_speech = speeches[first-1][diff_mod]
107 | pri_speech = speeches[first-1][sum%n1]
108 | sec_speech = speeches[sec-1][first%n2]
109 | row = create_example( path[dataset], hyper_params , n*(i-1) + j, ref_speech, pri_speech, sec_speech)
110 | if row is not None:
111 | batch.append(row)
112 | print(i)
113 | return batch
114 |
115 | def save_batch(dataset,data):
116 | df_path = os.path.join(path[dataset],'data_frame.csv')
117 | df = pd.read_csv(df_path)
118 | df_batch = pd.DataFrame(data = data, columns = columns)
119 | df = df.append(df_batch)
120 | df.to_csv(df_path,index=False)
121 |
122 | columns=['key','ref_speech','pri_speech','sec_speech','input_spec_path','output_spec_path','input_phase_path','output_phase_path','dvector_path']
123 | hyper_params = HyperParams()
124 | audio = Audio(hyper_params)
125 | dataset_path = os.path.join('drive','My Drive','LibriSpeech Dataset')
126 | path = {}
127 | path['dev'] = os.path.join(dataset_path,'LibriSpeech Dev Dataset')
128 | path['test'] = os.path.join(dataset_path,'LibriSpeech Test Dataset')
129 | path['train'] = os.path.join(dataset_path ,'LibriSpeech Train Dataset')
130 |
131 | with open(os.path.join(path['dev'],'dev_speeches.data'),'rb') as f:
132 | dev_speeches = pickle.load(f)
133 | with open(os.path.join(path['test'],'test_speeches.data'),'rb') as f:
134 | test_speeches = pickle.load(f)
135 | with open(os.path.join(path['train'],'train_speeches.data'),'rb') as f:
136 | train_speeches = pickle.load(f)
137 |
138 | embedder_path = os.path.join(dataset_path,"embedder.pt")
139 | embedder_pt = torch.load(embedder_path,map_location=torch.device('cpu'))
140 | embedder = SpeechEmbedder(hyper_params)
141 | embedder.load_state_dict(embedder_pt)
142 | embedder.eval()
143 |
144 | cpu_num = len(os.sched_getaffinity(0))
145 |
146 | #### Dev Dataset ####
147 | dataset = 'dev' # important global variable
148 | speeches = dev_speeches # important global variable
149 | n = len(dev_speeches) # important global variable
150 | print("number of speakers(dev set) : ",n)
151 | for i in range(n):
152 | random.shuffle(dev_speeches[i]) # shuffle the speeches of all speakers
153 | arr = list(range(1,n+1)) # create a list for all speakers
154 |
155 | data = []
156 | parity = 0 # important global variable
157 | with Pool(cpu_num) as p:
158 | res = p.map(create_dataset, arr , 4)
159 | for batch in res:
160 | if len(batch) > 0:
161 | data.extend(batch)
162 | save_batch('dev',data)
163 |
164 | data = []
165 | parity = 1 # important global variable
166 | with Pool(cpu_num) as p:
167 | res = p.map(create_dataset, arr , 4)
168 | for batch in res:
169 | if len(batch) > 0:
170 | data.extend(batch)
171 | save_batch('dev',data)
172 |
173 | #### Test dataset ####
174 | dataset = 'test' # important global variable
175 | speeches = test_speeches # important global variable
176 | n = len(test_speeches) # important global variable
177 | print("number of speakers(test set) : ",n)
178 | for i in range(n):
179 | random.shuffle(test_speeches[i]) # shuffle the speeches of all speakers
180 | arr = list(range(1,n+1)) # create a list for all speakers
181 |
182 | data = []
183 | parity = 0 # important global variable
184 | x = time.time()
185 | with Pool(cpu_num) as p:
186 | res = p.map(create_dataset, arr , 4)
187 | for batch in res:
188 | if len(batch) > 0:
189 | data.extend(batch)
190 | y = time.time()
191 | print(y-x)
192 | save_batch('test',data)
193 |
194 | data = []
195 | parity = 1 # important global variable
196 | x = time.time()
197 | with Pool(cpu_num) as p:
198 | res = p.map(create_dataset, arr , 4)
199 | for batch in res:
200 | if len(batch) > 0:
201 | data.extend(batch)
202 | y = time.time()
203 | print(y-x)
204 | save_batch('test',data)
205 |
206 | #### Train dataset ####
207 | dataset = 'train' # important global variable
208 | speeches = train_speeches # important global variable
209 | n = len(train_speeches) # important global variable
210 | print("number of speakers(train set) : ",n)
211 | for i in range(n):
212 | random.shuffle(train_speeches[i]) # shuffle the speeches of all speakers
213 | arr = list(range(1,n+1)) # create a list for all speakers
214 |
215 | data = []
216 | parity = 0 # important global variable
217 | with Pool(cpu_num) as p:
218 | res = p.map(create_dataset, arr , 4)
219 | for batch in res:
220 | if len(batch) > 0:
221 | data.extend(batch)
222 | save_batch('train',data)
223 |
224 | ### Run the following code only to create additional 30k samples for training set
225 | #data = []
226 | #parity = 1 # important global variable
227 | #with Pool(cpu_num) as p:
228 | # res = p.map(create_dataset, arr , 4)
229 | #for batch in res:
230 | # if len(batch) > 0:
231 | # data.extend(batch)
232 | #save_batch('train',data)
233 |
234 |
235 |
--------------------------------------------------------------------------------
/dataset/directory_structure.py:
--------------------------------------------------------------------------------
1 | import os
2 | import pandas as pd
3 | import shutil
4 |
5 | dataset_path = os.path.join('drive','My Drive','LibriSpeech Dataset')
6 | path = {}
7 | path['dev'] = os.path.join(dataset_path,'LibriSpeech Dev Dataset')
8 | path['test'] = os.path.join(dataset_path,'LibriSpeech Test Dataset')
9 | path['train'] = os.path.join(dataset_path ,'LibriSpeech Train Dataset')
10 |
11 | shutil.unpack_archive(os.path.join(dataset_path,'dev-clean.tar.gz'),os.path.join(dataset_path))
12 | # Rename the extracted folder LibriSpeech to LibriSpeech Dev Dataset
13 | shutil.unpack_archive(os.path.join(dataset_path,'test-clean.tar.gz'),os.path.join(dataset_path))
14 | # Rename the extracted folder LibriSpeech to LibriSpeech Test Dataset
15 | shutil.unpack_archive(os.path.join(dataset_path,'train-clean-100.tar.gz'),os.path.join(dataset_path))
16 | # Rename the extracted folder LibriSpeech to LibriSpeech Train Dataset
17 |
18 | for dataset in ('dev','test'):
19 | os.makedirs(os.path.join(path[dataset],'input_spec'),exist_ok=True)
20 | os.makedirs(os.path.join(path[dataset],'output_spec'),exist_ok=True)
21 | os.makedirs(os.path.join(path[dataset],'input_phase'),exist_ok=True)
22 | os.makedirs(os.path.join(path[dataset],'output_phase'),exist_ok=True)
23 | os.makedirs(os.path.join(path[dataset],'dvector'),exist_ok=True)
24 |
25 | def create_folders(i):
26 | os.makedirs(os.path.join(path['train'],'input_spec_'+i),exist_ok=True)
27 | os.makedirs(os.path.join(path['train'],'output_spec_'+i),exist_ok=True)
28 | os.makedirs(os.path.join(path['train'],'input_phase_'+i),exist_ok=True)
29 | os.makedirs(os.path.join(path['train'],'output_phase_'+i),exist_ok=True)
30 | os.makedirs(os.path.join(path['train'],'dvector_'+i),exist_ok=True)
31 |
32 | for i in range(8):
33 | create_folders(str(i))
34 |
35 | columns=['key','ref_speech','pri_speech','sec_speech','input_spec_path','output_spec_path','input_phase_path','output_phase_path','dvector_path']
36 | sample_data_frame = pd.DataFrame(data = [], columns=columns)
37 | for dataset in ('train','dev','test'):
38 | sample_data_frame.to_csv(os.path.join(path[dataset],'data_frame.csv'),index=False)
--------------------------------------------------------------------------------
/dataset/preload_training_dataset.py:
--------------------------------------------------------------------------------
1 | import os
2 | import pandas as pd
3 | import numpy as np
4 |
5 | def load_col_data(data_frame ,indices, start_pos, end_pos, col):
6 | col_list = []
7 | for i in range(start_pos,end_pos):
8 | idx = indices[i]
9 | col_list.append(np.load(data_frame[col][idx]))
10 | return np.array(col_list)
11 |
12 | def preload_training_data(cur_fraction, start_pos, end_pos):
13 | input_spec = load_col_data(df_train, list(range(num_samples)) , start_pos , end_pos ,'input_spec_path' )
14 | np.save(os.path.join(dataset_path,'PreLoad Training Dataset','fraction_'+str(cur_fraction),'input_spec'),input_spec)
15 | output_spec = load_col_data(df_train, list(range(num_samples)), start_pos, end_pos, 'output_spec_path')
16 | np.save(os.path.join(dataset_path,'PreLoad Training Dataset','fraction_'+str(cur_fraction),'output_spec'), output_spec)
17 | dvec = load_col_data(df_train, list(range(num_samples)), start_pos, end_pos, 'dvector_path')
18 | np.save(os.path.join(dataset_path,'PreLoad Training Dataset','fraction_'+str(cur_fraction),'dvec'),dvec)
19 |
20 | def load_all_data(dataset):
21 | output_spec = load_col_data(df, list(range(df.shape[0])), 0 , df.shape[0] ,'output_spec_path')
22 | output_phase = load_col_data(df,list(range(df.shape[0])), 0 , df.shape[0] ,'output_phase_path')
23 | input_spec = load_col_data(df, list(range(df.shape[0])), 0 , df.shape[0] ,'input_spec_path')
24 | input_phase = load_col_data(df,list(range(df.shape[0])), 0 , df.shape[0] ,'input_phase_path')
25 | dvec = load_col_data(df,list(range(df.shape[0])), 0 , df.shape[0] ,'dvector_path')
26 | np.save(os.path.join(path[dataset],'output_spec.npy'),output_spec)
27 | np.save(os.path.join(path[dataset],'output_phase.npy'),output_phase)
28 | np.save(os.path.join(path[dataset],'input_spec.npy'),input_spec)
29 | np.save(os.path.join(path[dataset],'input_phase.npy'),input_phase)
30 | np.save(os.path.join(path[dataset],'dvec.npy'),dvec)
31 |
32 | dataset_train = 'train'
33 | df_train = pd.read_csv(os.path.join(path[dataset_train],'data_frame.csv'))
34 | num_samples = df_train.shape[0]
35 |
36 | num_fractions = 8
37 | fraction_sizes = num_fractions * [ num_samples//num_fractions ]
38 | for i in range(num_samples%num_fractions):
39 | fraction_sizes[i]+=1
40 | print(fraction_sizes)
41 |
42 | start_pos = 0
43 | for i in range(num_fractions):
44 | end_pos = start_pos + fraction_sizes[i]
45 | preload_training_data(i,start_pos, end_pos)
46 | start_pos = end_pos
47 |
48 | load_all_data('dev')
49 | load_all_data('test')
50 |
--------------------------------------------------------------------------------
/dataset/speech_collection.py:
--------------------------------------------------------------------------------
1 | import glob
2 | import pickle
3 | import os
4 | dataset_path = os.path.join('drive','My Drive','LibriSpeech Dataset')
5 | path = {}
6 | path['dev'] = os.path.join(dataset_path,'LibriSpeech Dev Dataset')
7 | path['test'] = os.path.join(dataset_path,'LibriSpeech Test Dataset')
8 | path['train'] = os.path.join(dataset_path ,'LibriSpeech Train Dataset')
9 |
10 | #### Run this cell only the first time ####
11 | dev_base_path = os.path.join(path['dev'],'dev-clean')
12 | test_base_path = os.path.join(path['test'],'test-clean')
13 | train_base_path = os.path.join(path['train'],'train-clean-100')
14 |
15 | #### Run this cell only the first time ####
16 | dev_spks = os.listdir(dev_base_path)
17 | # list of all speaker folders
18 | dev_speeches = [glob.glob(os.path.join(dev_base_path,spk,'*','*.flac'),recursive=True) for spk in dev_spks]
19 | dev_speeches = [speeches for speeches in dev_speeches if len(speeches)>=2]
20 | # list of lists containing speeches of a speaker
21 | test_spks = os.listdir(test_base_path)
22 | # list of all speaker folders
23 | test_speeches = [glob.glob(os.path.join(test_base_path,spk,'*','*.flac'),recursive=True) for spk in test_spks]
24 | test_speeches = [speeches for speeches in test_speeches if len(speeches)>=2]
25 | # list of lists containing speeches of a speaker
26 | train_spks = os.listdir(train_base_path)
27 | # list of all speaker folders
28 | train_speeches = [glob.glob(os.path.join(train_base_path,spk,'*','*.flac'),recursive=True) for spk in train_spks]
29 | train_speeches = [speeches for speeches in train_speeches if len(speeches)>=2]
30 | # list of lists containing speeches of a speaker
31 |
32 | ##### Run this cell only the first time #####
33 | with open(os.path.join(path['dev'],'dev_speeches.data'),'wb') as f:
34 | pickle.dump(dev_speeches,f)
35 | with open(os.path.join(path['test'],'test_speeches.data'),'wb') as f:
36 | pickle.dump(test_speeches,f)
37 | with open(os.path.join(path['train'],'train_speeches.data'),'wb') as f:
38 | pickle.dump(train_speeches,f)
39 |
40 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | .dart_tool/
26 | .flutter-plugins
27 | .flutter-plugins-dependencies
28 | .packages
29 | .pub-cache/
30 | .pub/
31 | /build/
32 |
33 | # Web related
34 | lib/generated_plugin_registrant.dart
35 |
36 | # Symbolication related
37 | app.*.symbols
38 |
39 | # Obfuscation related
40 | app.*.map.json
41 |
42 | # Exceptions to above rules.
43 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
44 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/README.md:
--------------------------------------------------------------------------------
1 | # Voice Filter App
2 |
3 | A sample user-end app for the voicefilter implementation.
4 |
5 | ## Getting Started
6 |
7 | This project is a starting point for a Flutter application.
8 |
9 | A few resources to get you started if this is your first Flutter project:
10 |
11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
13 |
14 | For help getting started with Flutter, view our
15 | [online documentation](https://flutter.dev/docs), which offers tutorials,
16 | samples, guidance on mobile development, and a full API reference.
17 |
18 | ## App Snippet
19 |
20 |
21 |
22 | ## Instructions
23 |
24 | * Add Firebase to your app
25 |
26 | https://firebase.google.com/docs/flutter/setup
27 |
28 |
29 | * Deploy the voicefilter model in the parent directory using [Flask]() to any hosting service like [Heroku](www.heroku.com
30 | ), [GCP](cloud.google.com
31 | ), [AWS](aws.amazon.com
32 | ) and so on. Then add your API KEY in `services/api.dart`
33 |
34 | ```
35 | String postUrl = "< API KEY >";
36 | ```
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | android {
29 | compileSdkVersion 28
30 |
31 | sourceSets {
32 | main.java.srcDirs += 'src/main/kotlin'
33 | }
34 |
35 | lintOptions {
36 | disable 'InvalidPackage'
37 | }
38 |
39 | defaultConfig {
40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
41 | applicationId "com.example.voicefilter"
42 | minSdkVersion 16
43 | targetSdkVersion 28
44 | versionCode flutterVersionCode.toInteger()
45 | versionName flutterVersionName
46 | multiDexEnabled true
47 | }
48 |
49 | buildTypes {
50 | release {
51 | // TODO: Add your own signing config for the release build.
52 | // Signing with the debug keys for now, so `flutter run --release` works.
53 | signingConfig signingConfigs.debug
54 | }
55 | }
56 | }
57 |
58 | flutter {
59 | source '../..'
60 | }
61 |
62 | dependencies {
63 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
64 | }
65 |
66 | apply plugin: 'com.google.gms.google-services'
67 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
11 |
15 |
22 |
26 |
30 |
35 |
39 |
40 |
41 |
42 |
43 |
44 |
46 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/android/app/src/main/kotlin/com/example/voicefilter/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.voicefilter
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.5.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | classpath 'com.google.gms:google-services:4.3.3'
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | google()
18 | jcenter()
19 | }
20 | }
21 |
22 | rootProject.buildDir = '../build'
23 | subprojects {
24 | project.buildDir = "${rootProject.buildDir}/${project.name}"
25 | }
26 | subprojects {
27 | project.evaluationDependsOn(':app')
28 | }
29 |
30 | task clean(type: Delete) {
31 | delete rootProject.buildDir
32 | }
33 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.enableR8=true
3 | android.useAndroidX=true
4 | android.enableJetifier=true
5 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
7 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/assets/audio1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/assets/audio1.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/assets/audio2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/assets/audio2.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/assets/audio3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/assets/audio3.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/fonts/Montserrat-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/fonts/Montserrat-Regular.ttf
--------------------------------------------------------------------------------
/flutter app/voicefilter/fonts/Poppins-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/fonts/Poppins-Regular.ttf
--------------------------------------------------------------------------------
/flutter app/voicefilter/fonts/Raleway-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/fonts/Raleway-Regular.ttf
--------------------------------------------------------------------------------
/flutter app/voicefilter/fonts/Spartan-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/fonts/Spartan-Regular.ttf
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/app.flx
22 | Flutter/app.zip
23 | Flutter/flutter_assets/
24 | Flutter/flutter_export_environment.sh
25 | ServiceDefinitions.json
26 | Runner/GeneratedPluginRegistrant.*
27 |
28 | # Exceptions to above rules.
29 | !default.mode1v3
30 | !default.mode2v3
31 | !default.pbxuser
32 | !default.perspectivev3
33 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
16 | /* End PBXBuildFile section */
17 |
18 | /* Begin PBXCopyFilesBuildPhase section */
19 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
20 | isa = PBXCopyFilesBuildPhase;
21 | buildActionMask = 2147483647;
22 | dstPath = "";
23 | dstSubfolderSpec = 10;
24 | files = (
25 | );
26 | name = "Embed Frameworks";
27 | runOnlyForDeploymentPostprocessing = 0;
28 | };
29 | /* End PBXCopyFilesBuildPhase section */
30 |
31 | /* Begin PBXFileReference section */
32 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
33 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
34 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
35 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
36 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
37 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
38 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
39 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
40 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
41 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
42 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
43 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
44 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
45 | /* End PBXFileReference section */
46 |
47 | /* Begin PBXFrameworksBuildPhase section */
48 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
49 | isa = PBXFrameworksBuildPhase;
50 | buildActionMask = 2147483647;
51 | files = (
52 | );
53 | runOnlyForDeploymentPostprocessing = 0;
54 | };
55 | /* End PBXFrameworksBuildPhase section */
56 |
57 | /* Begin PBXGroup section */
58 | 9740EEB11CF90186004384FC /* Flutter */ = {
59 | isa = PBXGroup;
60 | children = (
61 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
62 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
63 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
64 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
65 | );
66 | name = Flutter;
67 | sourceTree = "";
68 | };
69 | 97C146E51CF9000F007C117D = {
70 | isa = PBXGroup;
71 | children = (
72 | 9740EEB11CF90186004384FC /* Flutter */,
73 | 97C146F01CF9000F007C117D /* Runner */,
74 | 97C146EF1CF9000F007C117D /* Products */,
75 | );
76 | sourceTree = "";
77 | };
78 | 97C146EF1CF9000F007C117D /* Products */ = {
79 | isa = PBXGroup;
80 | children = (
81 | 97C146EE1CF9000F007C117D /* Runner.app */,
82 | );
83 | name = Products;
84 | sourceTree = "";
85 | };
86 | 97C146F01CF9000F007C117D /* Runner */ = {
87 | isa = PBXGroup;
88 | children = (
89 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
90 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
91 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
92 | 97C147021CF9000F007C117D /* Info.plist */,
93 | 97C146F11CF9000F007C117D /* Supporting Files */,
94 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
95 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
96 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
97 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
98 | );
99 | path = Runner;
100 | sourceTree = "";
101 | };
102 | 97C146F11CF9000F007C117D /* Supporting Files */ = {
103 | isa = PBXGroup;
104 | children = (
105 | );
106 | name = "Supporting Files";
107 | sourceTree = "";
108 | };
109 | /* End PBXGroup section */
110 |
111 | /* Begin PBXNativeTarget section */
112 | 97C146ED1CF9000F007C117D /* Runner */ = {
113 | isa = PBXNativeTarget;
114 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
115 | buildPhases = (
116 | 9740EEB61CF901F6004384FC /* Run Script */,
117 | 97C146EA1CF9000F007C117D /* Sources */,
118 | 97C146EB1CF9000F007C117D /* Frameworks */,
119 | 97C146EC1CF9000F007C117D /* Resources */,
120 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
121 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
122 | );
123 | buildRules = (
124 | );
125 | dependencies = (
126 | );
127 | name = Runner;
128 | productName = Runner;
129 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
130 | productType = "com.apple.product-type.application";
131 | };
132 | /* End PBXNativeTarget section */
133 |
134 | /* Begin PBXProject section */
135 | 97C146E61CF9000F007C117D /* Project object */ = {
136 | isa = PBXProject;
137 | attributes = {
138 | LastUpgradeCheck = 1020;
139 | ORGANIZATIONNAME = "";
140 | TargetAttributes = {
141 | 97C146ED1CF9000F007C117D = {
142 | CreatedOnToolsVersion = 7.3.1;
143 | LastSwiftMigration = 1100;
144 | };
145 | };
146 | };
147 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
148 | compatibilityVersion = "Xcode 9.3";
149 | developmentRegion = en;
150 | hasScannedForEncodings = 0;
151 | knownRegions = (
152 | en,
153 | Base,
154 | );
155 | mainGroup = 97C146E51CF9000F007C117D;
156 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
157 | projectDirPath = "";
158 | projectRoot = "";
159 | targets = (
160 | 97C146ED1CF9000F007C117D /* Runner */,
161 | );
162 | };
163 | /* End PBXProject section */
164 |
165 | /* Begin PBXResourcesBuildPhase section */
166 | 97C146EC1CF9000F007C117D /* Resources */ = {
167 | isa = PBXResourcesBuildPhase;
168 | buildActionMask = 2147483647;
169 | files = (
170 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
171 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
172 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
173 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
174 | );
175 | runOnlyForDeploymentPostprocessing = 0;
176 | };
177 | /* End PBXResourcesBuildPhase section */
178 |
179 | /* Begin PBXShellScriptBuildPhase section */
180 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
181 | isa = PBXShellScriptBuildPhase;
182 | buildActionMask = 2147483647;
183 | files = (
184 | );
185 | inputPaths = (
186 | );
187 | name = "Thin Binary";
188 | outputPaths = (
189 | );
190 | runOnlyForDeploymentPostprocessing = 0;
191 | shellPath = /bin/sh;
192 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
193 | };
194 | 9740EEB61CF901F6004384FC /* Run Script */ = {
195 | isa = PBXShellScriptBuildPhase;
196 | buildActionMask = 2147483647;
197 | files = (
198 | );
199 | inputPaths = (
200 | );
201 | name = "Run Script";
202 | outputPaths = (
203 | );
204 | runOnlyForDeploymentPostprocessing = 0;
205 | shellPath = /bin/sh;
206 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
207 | };
208 | /* End PBXShellScriptBuildPhase section */
209 |
210 | /* Begin PBXSourcesBuildPhase section */
211 | 97C146EA1CF9000F007C117D /* Sources */ = {
212 | isa = PBXSourcesBuildPhase;
213 | buildActionMask = 2147483647;
214 | files = (
215 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
216 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
217 | );
218 | runOnlyForDeploymentPostprocessing = 0;
219 | };
220 | /* End PBXSourcesBuildPhase section */
221 |
222 | /* Begin PBXVariantGroup section */
223 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
224 | isa = PBXVariantGroup;
225 | children = (
226 | 97C146FB1CF9000F007C117D /* Base */,
227 | );
228 | name = Main.storyboard;
229 | sourceTree = "";
230 | };
231 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
232 | isa = PBXVariantGroup;
233 | children = (
234 | 97C147001CF9000F007C117D /* Base */,
235 | );
236 | name = LaunchScreen.storyboard;
237 | sourceTree = "";
238 | };
239 | /* End PBXVariantGroup section */
240 |
241 | /* Begin XCBuildConfiguration section */
242 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
243 | isa = XCBuildConfiguration;
244 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
245 | buildSettings = {
246 | ALWAYS_SEARCH_USER_PATHS = NO;
247 | CLANG_ANALYZER_NONNULL = YES;
248 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
249 | CLANG_CXX_LIBRARY = "libc++";
250 | CLANG_ENABLE_MODULES = YES;
251 | CLANG_ENABLE_OBJC_ARC = YES;
252 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
253 | CLANG_WARN_BOOL_CONVERSION = YES;
254 | CLANG_WARN_COMMA = YES;
255 | CLANG_WARN_CONSTANT_CONVERSION = YES;
256 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
257 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
258 | CLANG_WARN_EMPTY_BODY = YES;
259 | CLANG_WARN_ENUM_CONVERSION = YES;
260 | CLANG_WARN_INFINITE_RECURSION = YES;
261 | CLANG_WARN_INT_CONVERSION = YES;
262 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
263 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
264 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
265 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
266 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
267 | CLANG_WARN_STRICT_PROTOTYPES = YES;
268 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
269 | CLANG_WARN_UNREACHABLE_CODE = YES;
270 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
271 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
272 | COPY_PHASE_STRIP = NO;
273 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
274 | ENABLE_NS_ASSERTIONS = NO;
275 | ENABLE_STRICT_OBJC_MSGSEND = YES;
276 | GCC_C_LANGUAGE_STANDARD = gnu99;
277 | GCC_NO_COMMON_BLOCKS = YES;
278 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
279 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
280 | GCC_WARN_UNDECLARED_SELECTOR = YES;
281 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
282 | GCC_WARN_UNUSED_FUNCTION = YES;
283 | GCC_WARN_UNUSED_VARIABLE = YES;
284 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
285 | MTL_ENABLE_DEBUG_INFO = NO;
286 | SDKROOT = iphoneos;
287 | SUPPORTED_PLATFORMS = iphoneos;
288 | TARGETED_DEVICE_FAMILY = "1,2";
289 | VALIDATE_PRODUCT = YES;
290 | };
291 | name = Profile;
292 | };
293 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
294 | isa = XCBuildConfiguration;
295 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
296 | buildSettings = {
297 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
298 | CLANG_ENABLE_MODULES = YES;
299 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
300 | ENABLE_BITCODE = NO;
301 | FRAMEWORK_SEARCH_PATHS = (
302 | "$(inherited)",
303 | "$(PROJECT_DIR)/Flutter",
304 | );
305 | INFOPLIST_FILE = Runner/Info.plist;
306 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
307 | LIBRARY_SEARCH_PATHS = (
308 | "$(inherited)",
309 | "$(PROJECT_DIR)/Flutter",
310 | );
311 | PRODUCT_BUNDLE_IDENTIFIER = com.example.voicefilter;
312 | PRODUCT_NAME = "$(TARGET_NAME)";
313 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
314 | SWIFT_VERSION = 5.0;
315 | VERSIONING_SYSTEM = "apple-generic";
316 | };
317 | name = Profile;
318 | };
319 | 97C147031CF9000F007C117D /* Debug */ = {
320 | isa = XCBuildConfiguration;
321 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
322 | buildSettings = {
323 | ALWAYS_SEARCH_USER_PATHS = NO;
324 | CLANG_ANALYZER_NONNULL = YES;
325 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
326 | CLANG_CXX_LIBRARY = "libc++";
327 | CLANG_ENABLE_MODULES = YES;
328 | CLANG_ENABLE_OBJC_ARC = YES;
329 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
330 | CLANG_WARN_BOOL_CONVERSION = YES;
331 | CLANG_WARN_COMMA = YES;
332 | CLANG_WARN_CONSTANT_CONVERSION = YES;
333 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
334 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
335 | CLANG_WARN_EMPTY_BODY = YES;
336 | CLANG_WARN_ENUM_CONVERSION = YES;
337 | CLANG_WARN_INFINITE_RECURSION = YES;
338 | CLANG_WARN_INT_CONVERSION = YES;
339 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
340 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
341 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
342 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
343 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
344 | CLANG_WARN_STRICT_PROTOTYPES = YES;
345 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
346 | CLANG_WARN_UNREACHABLE_CODE = YES;
347 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
348 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
349 | COPY_PHASE_STRIP = NO;
350 | DEBUG_INFORMATION_FORMAT = dwarf;
351 | ENABLE_STRICT_OBJC_MSGSEND = YES;
352 | ENABLE_TESTABILITY = YES;
353 | GCC_C_LANGUAGE_STANDARD = gnu99;
354 | GCC_DYNAMIC_NO_PIC = NO;
355 | GCC_NO_COMMON_BLOCKS = YES;
356 | GCC_OPTIMIZATION_LEVEL = 0;
357 | GCC_PREPROCESSOR_DEFINITIONS = (
358 | "DEBUG=1",
359 | "$(inherited)",
360 | );
361 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
362 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
363 | GCC_WARN_UNDECLARED_SELECTOR = YES;
364 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
365 | GCC_WARN_UNUSED_FUNCTION = YES;
366 | GCC_WARN_UNUSED_VARIABLE = YES;
367 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
368 | MTL_ENABLE_DEBUG_INFO = YES;
369 | ONLY_ACTIVE_ARCH = YES;
370 | SDKROOT = iphoneos;
371 | TARGETED_DEVICE_FAMILY = "1,2";
372 | };
373 | name = Debug;
374 | };
375 | 97C147041CF9000F007C117D /* Release */ = {
376 | isa = XCBuildConfiguration;
377 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
378 | buildSettings = {
379 | ALWAYS_SEARCH_USER_PATHS = NO;
380 | CLANG_ANALYZER_NONNULL = YES;
381 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
382 | CLANG_CXX_LIBRARY = "libc++";
383 | CLANG_ENABLE_MODULES = YES;
384 | CLANG_ENABLE_OBJC_ARC = YES;
385 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
386 | CLANG_WARN_BOOL_CONVERSION = YES;
387 | CLANG_WARN_COMMA = YES;
388 | CLANG_WARN_CONSTANT_CONVERSION = YES;
389 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
390 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
391 | CLANG_WARN_EMPTY_BODY = YES;
392 | CLANG_WARN_ENUM_CONVERSION = YES;
393 | CLANG_WARN_INFINITE_RECURSION = YES;
394 | CLANG_WARN_INT_CONVERSION = YES;
395 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
396 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
397 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
398 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
399 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
400 | CLANG_WARN_STRICT_PROTOTYPES = YES;
401 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
402 | CLANG_WARN_UNREACHABLE_CODE = YES;
403 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
404 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
405 | COPY_PHASE_STRIP = NO;
406 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
407 | ENABLE_NS_ASSERTIONS = NO;
408 | ENABLE_STRICT_OBJC_MSGSEND = YES;
409 | GCC_C_LANGUAGE_STANDARD = gnu99;
410 | GCC_NO_COMMON_BLOCKS = YES;
411 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
412 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
413 | GCC_WARN_UNDECLARED_SELECTOR = YES;
414 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
415 | GCC_WARN_UNUSED_FUNCTION = YES;
416 | GCC_WARN_UNUSED_VARIABLE = YES;
417 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
418 | MTL_ENABLE_DEBUG_INFO = NO;
419 | SDKROOT = iphoneos;
420 | SUPPORTED_PLATFORMS = iphoneos;
421 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
422 | TARGETED_DEVICE_FAMILY = "1,2";
423 | VALIDATE_PRODUCT = YES;
424 | };
425 | name = Release;
426 | };
427 | 97C147061CF9000F007C117D /* Debug */ = {
428 | isa = XCBuildConfiguration;
429 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
430 | buildSettings = {
431 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
432 | CLANG_ENABLE_MODULES = YES;
433 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
434 | ENABLE_BITCODE = NO;
435 | FRAMEWORK_SEARCH_PATHS = (
436 | "$(inherited)",
437 | "$(PROJECT_DIR)/Flutter",
438 | );
439 | INFOPLIST_FILE = Runner/Info.plist;
440 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
441 | LIBRARY_SEARCH_PATHS = (
442 | "$(inherited)",
443 | "$(PROJECT_DIR)/Flutter",
444 | );
445 | PRODUCT_BUNDLE_IDENTIFIER = com.example.voicefilter;
446 | PRODUCT_NAME = "$(TARGET_NAME)";
447 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
448 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
449 | SWIFT_VERSION = 5.0;
450 | VERSIONING_SYSTEM = "apple-generic";
451 | };
452 | name = Debug;
453 | };
454 | 97C147071CF9000F007C117D /* Release */ = {
455 | isa = XCBuildConfiguration;
456 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
457 | buildSettings = {
458 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
459 | CLANG_ENABLE_MODULES = YES;
460 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
461 | ENABLE_BITCODE = NO;
462 | FRAMEWORK_SEARCH_PATHS = (
463 | "$(inherited)",
464 | "$(PROJECT_DIR)/Flutter",
465 | );
466 | INFOPLIST_FILE = Runner/Info.plist;
467 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
468 | LIBRARY_SEARCH_PATHS = (
469 | "$(inherited)",
470 | "$(PROJECT_DIR)/Flutter",
471 | );
472 | PRODUCT_BUNDLE_IDENTIFIER = com.example.voicefilter;
473 | PRODUCT_NAME = "$(TARGET_NAME)";
474 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
475 | SWIFT_VERSION = 5.0;
476 | VERSIONING_SYSTEM = "apple-generic";
477 | };
478 | name = Release;
479 | };
480 | /* End XCBuildConfiguration section */
481 |
482 | /* Begin XCConfigurationList section */
483 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
484 | isa = XCConfigurationList;
485 | buildConfigurations = (
486 | 97C147031CF9000F007C117D /* Debug */,
487 | 97C147041CF9000F007C117D /* Release */,
488 | 249021D3217E4FDB00AE95B9 /* Profile */,
489 | );
490 | defaultConfigurationIsVisible = 0;
491 | defaultConfigurationName = Release;
492 | };
493 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
494 | isa = XCConfigurationList;
495 | buildConfigurations = (
496 | 97C147061CF9000F007C117D /* Debug */,
497 | 97C147071CF9000F007C117D /* Release */,
498 | 249021D4217E4FDB00AE95B9 /* Profile */,
499 | );
500 | defaultConfigurationIsVisible = 0;
501 | defaultConfigurationName = Release;
502 | };
503 | /* End XCConfigurationList section */
504 | };
505 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
506 | }
507 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosX7/voice-filter/79b07aeddea796e895bdd5fc48dc352bd3eb6ea4/flutter app/voicefilter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | voicefilter
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:voicefilter/services/auth_manager.dart';
3 | import 'package:voicefilter/utilities/constants.dart';
4 |
5 | void main() {
6 | runApp(MyApp());
7 | }
8 |
9 | class MyApp extends StatelessWidget {
10 | // This widget is the root of your application.
11 | @override
12 | Widget build(BuildContext context) {
13 | return MaterialApp(
14 | title: 'voice filter',
15 | debugShowCheckedModeBanner: false,
16 | theme: ThemeData(
17 | primaryColor: myBlue,
18 | primarySwatch: Colors.blue,
19 | visualDensity: VisualDensity.adaptivePlatformDensity,
20 | ),
21 | home: AuthManager(),
22 | );
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/lib/screens/embedding_screen.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:io' as io;
3 | import 'package:file/file.dart';
4 | import 'package:firebase_storage/firebase_storage.dart';
5 | import 'package:flutter/material.dart';
6 | import 'package:font_awesome_flutter/font_awesome_flutter.dart';
7 | import 'package:path_provider/path_provider.dart';
8 | import 'package:flutter_audio_recorder/flutter_audio_recorder.dart';
9 | import 'package:file/local.dart';
10 | import 'package:voicefilter/screens/filter_screen.dart';
11 | import 'package:voicefilter/services/auth_service.dart';
12 | import 'package:voicefilter/utilities/constants.dart';
13 | import 'package:firebase_database/firebase_database.dart';
14 | import 'package:firebase_auth/firebase_auth.dart';
15 |
16 | class EmbeddingScreen extends StatefulWidget {
17 | final LocalFileSystem localFileSystem;
18 | EmbeddingScreen({localFileSystem})
19 | : this.localFileSystem = localFileSystem ?? LocalFileSystem();
20 | @override
21 | _EmbeddingScreenState createState() => _EmbeddingScreenState();
22 | }
23 |
24 | class _EmbeddingScreenState extends State {
25 | FlutterAudioRecorder _recorder;
26 | Recording _current;
27 | RecordingStatus _currentStatus = RecordingStatus.Unset;
28 |
29 | _init() async {
30 | try {
31 | if (await FlutterAudioRecorder.hasPermissions) {
32 | String customPath = '/embedding_';
33 | io.Directory appDocDirectory;
34 | if (io.Platform.isIOS) {
35 | appDocDirectory = await getApplicationDocumentsDirectory();
36 | } else {
37 | appDocDirectory = await getExternalStorageDirectory();
38 | }
39 |
40 | // can add extension like ".mp4" ".wav" ".m4a" ".aac"
41 | customPath =
42 | appDocDirectory.path + customPath + DateTime.now().toString();
43 |
44 | _recorder =
45 | FlutterAudioRecorder(customPath, audioFormat: AudioFormat.WAV);
46 |
47 | await _recorder.initialized;
48 | // after initialization
49 | var current = await _recorder.current(channel: 0);
50 | print(current);
51 | // should be "Initialized", if all working fine
52 | setState(() {
53 | _current = current;
54 | _currentStatus = current.status;
55 | print(_currentStatus);
56 | });
57 | } else {
58 | Scaffold.of(context).showSnackBar(
59 | SnackBar(content: Text("You must accept permissions")));
60 | }
61 | } catch (e) {
62 | print(e);
63 | }
64 | }
65 |
66 | @override
67 | void initState() {
68 | super.initState();
69 | _init();
70 | }
71 |
72 | @override
73 | Widget build(BuildContext context) {
74 | double width = MediaQuery.of(context).size.width;
75 | return SafeArea(
76 | child: Scaffold(
77 | backgroundColor: Colors.white,
78 | body: _currentStatus == RecordingStatus.Unset
79 | ? Center(
80 | child: CircularProgressIndicator(
81 | valueColor: AlwaysStoppedAnimation(
82 | myBlue,
83 | ),
84 | ),
85 | )
86 | : Column(
87 | children: [
88 | Expanded(
89 | child: SingleChildScrollView(
90 | child: Column(
91 | crossAxisAlignment: CrossAxisAlignment.start,
92 | mainAxisAlignment: MainAxisAlignment.spaceAround,
93 | children: [
94 | SizedBox(
95 | height: 20,
96 | ),
97 | Image.asset(
98 | 'assets/audio1.png',
99 | width: width,
100 | ),
101 | SizedBox(
102 | height: 40,
103 | ),
104 | Container(
105 | padding: EdgeInsets.symmetric(
106 | horizontal: 20,
107 | ),
108 | child: Text(
109 | "Welcome! thank you for signing up\nCan you please greet us with a 'hello'\nWe'll use it as your reference speech for the voice filter",
110 | textScaleFactor: 1.1,
111 | style: TextStyle(
112 | letterSpacing: 1.1,
113 | color: Colors.black54,
114 | fontWeight: FontWeight.w700,
115 | fontFamily: 'Raleway',
116 | ),
117 | ),
118 | ),
119 | ],
120 | ),
121 | ),
122 | ),
123 | Row(
124 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
125 | children: [
126 | IconButton(
127 | icon: Icon(
128 | FontAwesomeIcons.stopCircle,
129 | color: myBlue,
130 | ),
131 | onPressed: _currentStatus != RecordingStatus.Unset
132 | ? _stop
133 | : null,
134 | ),
135 | Column(
136 | children: [
137 | _buildText(_currentStatus),
138 | SizedBox(
139 | height: 10,
140 | ),
141 | InkWell(
142 | onTap: micResponse,
143 | child: CircleAvatar(
144 | backgroundColor: myBlue,
145 | radius: 25,
146 | child: Icon(
147 | Icons.mic,
148 | color: Colors.white,
149 | ),
150 | ),
151 | ),
152 | SizedBox(
153 | height: 20,
154 | ),
155 | ],
156 | ),
157 | IconButton(
158 | icon: Icon(
159 | FontAwesomeIcons.signOutAlt,
160 | color: myBlue,
161 | ),
162 | onPressed: _logout,
163 | ),
164 | ],
165 | ),
166 | ],
167 | ),
168 | ),
169 | );
170 | }
171 |
172 | void micResponse() {
173 | switch (_currentStatus) {
174 | case RecordingStatus.Initialized:
175 | {
176 | _start();
177 | break;
178 | }
179 | case RecordingStatus.Recording:
180 | {
181 | _pause();
182 | break;
183 | }
184 | case RecordingStatus.Paused:
185 | {
186 | _resume();
187 | break;
188 | }
189 | case RecordingStatus.Stopped:
190 | {
191 | _init();
192 | break;
193 | }
194 | default:
195 | break;
196 | }
197 | }
198 |
199 | Future _logout() async {
200 | await FirebaseAuthentication().signOut(context);
201 | }
202 |
203 | _start() async {
204 | try {
205 | await _recorder.start();
206 | var recording = await _recorder.current(channel: 0);
207 | setState(() {
208 | _current = recording;
209 | });
210 |
211 | const tick = const Duration(milliseconds: 50);
212 | Timer.periodic(tick, (Timer t) async {
213 | if (_currentStatus == RecordingStatus.Stopped) {
214 | t.cancel();
215 | }
216 |
217 | var current = await _recorder.current(channel: 0);
218 | setState(() {
219 | _current = current;
220 | _currentStatus = _current.status;
221 | });
222 | });
223 | } catch (e) {
224 | print(e);
225 | }
226 | }
227 |
228 | _resume() async {
229 | await _recorder.resume();
230 | setState(() {});
231 | }
232 |
233 | _pause() async {
234 | await _recorder.pause();
235 | setState(() {});
236 | }
237 |
238 | Future uploadReferenceSpeech() async {
239 | FirebaseUser user = await FirebaseAuth.instance.currentUser();
240 | DatabaseReference dbRef = FirebaseDatabase.instance.reference();
241 | final StorageReference storageRef = FirebaseStorage.instance.ref();
242 | io.File audioFile = io.File(_current.path);
243 |
244 | final StorageUploadTask uploadTask = storageRef
245 | .child("ref_speech")
246 | .child(user.email + ".wav")
247 | .putFile(audioFile);
248 | var audioUrl = await (await uploadTask.onComplete).ref.getDownloadURL();
249 | print(audioUrl);
250 |
251 | dbRef.child(user.email.split('@')[0]).update({
252 | 'embedding': audioUrl,
253 | });
254 | }
255 |
256 | _stop() async {
257 | var result = await _recorder.stop();
258 | print("Stop recording: ${result.path}");
259 | print("Stop recording: ${result.duration}");
260 | File file = widget.localFileSystem.file(result.path);
261 | print("File length: ${await file.length()}");
262 |
263 | setState(() {
264 | _current = result;
265 | _currentStatus = _current.status;
266 | });
267 |
268 | await uploadReferenceSpeech().whenComplete(() {
269 | Navigator.pushReplacement(
270 | context,
271 | MaterialPageRoute(
272 | builder: (context) => FilterScreen(),
273 | ),
274 | );
275 | });
276 | }
277 |
278 | Widget _buildText(RecordingStatus status) {
279 | var text = "";
280 | switch (_currentStatus) {
281 | case RecordingStatus.Initialized:
282 | {
283 | text = 'Start';
284 | break;
285 | }
286 | case RecordingStatus.Recording:
287 | {
288 | text = 'Pause';
289 | break;
290 | }
291 | case RecordingStatus.Paused:
292 | {
293 | text = 'Resume';
294 | break;
295 | }
296 | case RecordingStatus.Stopped:
297 | {
298 | text = 'Initialize';
299 | break;
300 | }
301 | default:
302 | break;
303 | }
304 | return Text(
305 | text,
306 | style: TextStyle(
307 | color: myBlue,
308 | letterSpacing: 1.4,
309 | fontWeight: FontWeight.w900,
310 | fontFamily: 'Spartan',
311 | ),
312 | );
313 | }
314 | }
315 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/lib/screens/filter_screen.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:io' as io;
3 | import 'package:file/file.dart';
4 | import 'package:firebase_database/firebase_database.dart';
5 | import 'package:firebase_storage/firebase_storage.dart';
6 | import 'package:flutter/material.dart';
7 | import 'package:font_awesome_flutter/font_awesome_flutter.dart';
8 | import 'package:path_provider/path_provider.dart';
9 | import 'package:flutter_audio_recorder/flutter_audio_recorder.dart';
10 | import 'package:file/local.dart';
11 | import 'package:voicefilter/services/api.dart';
12 | import 'package:voicefilter/services/auth_service.dart';
13 | import 'package:voicefilter/utilities/constants.dart';
14 | import 'package:voicefilter/widgets/custom_painter.dart';
15 | import 'package:voicefilter/widgets/player_widget.dart';
16 | import 'package:firebase_auth/firebase_auth.dart';
17 |
18 | class FilterScreen extends StatefulWidget {
19 | @override
20 | _FilterScreenState createState() => _FilterScreenState();
21 | }
22 |
23 | class UserData {
24 | String userEmail;
25 | String refUrl;
26 | UserData(this.userEmail, this.refUrl);
27 | }
28 |
29 | class _FilterScreenState extends State {
30 | Future getUserData() async {
31 | String userEmail;
32 | String refUrl;
33 | FirebaseUser user = await FirebaseAuth.instance.currentUser();
34 | userEmail = user.email.split('@')[0];
35 | DatabaseReference dbRef =
36 | FirebaseDatabase.instance.reference().child(userEmail);
37 | await dbRef.once().then((DataSnapshot snapshot) {
38 | refUrl = snapshot.value["embedding"];
39 | print("user :" + userEmail);
40 | print("ref :" + refUrl);
41 | });
42 |
43 | return UserData(userEmail, refUrl);
44 | }
45 |
46 | @override
47 | Widget build(BuildContext context) {
48 | return FutureBuilder(
49 | future: getUserData(),
50 | builder: (context, snapshot) {
51 | if (snapshot.hasData) {
52 | return VoiceFilter(
53 | userData: snapshot.data,
54 | );
55 | } else
56 | return Scaffold(
57 | backgroundColor: Colors.white,
58 | body: Center(
59 | child: CircularProgressIndicator(
60 | valueColor: AlwaysStoppedAnimation(myBlue),
61 | ),
62 | ),
63 | );
64 | },
65 | );
66 | }
67 | }
68 |
69 | class VoiceFilter extends StatefulWidget {
70 | final UserData userData;
71 | final LocalFileSystem localFileSystem;
72 | VoiceFilter({
73 | localFileSystem,
74 | this.userData,
75 | }) : this.localFileSystem = localFileSystem ?? LocalFileSystem();
76 | @override
77 | _VoiceFilterState createState() => _VoiceFilterState();
78 | }
79 |
80 | class _VoiceFilterState extends State {
81 | FlutterAudioRecorder _recorder;
82 | Recording _current;
83 | RecordingStatus _currentStatus = RecordingStatus.Unset;
84 | String timeKey;
85 |
86 | @override
87 | void initState() {
88 | super.initState();
89 | _init();
90 | print("init 2:");
91 | print(widget.userData.refUrl);
92 | }
93 |
94 | Widget getCirclePainter() {
95 | double percentage = ((120 + _current.metering.averagePower) / 1.2);
96 | return Container(
97 | height: 50,
98 | width: 50,
99 | child: CustomPaint(
100 | foregroundPainter: CirclePainter(
101 | lineColor: myBlue.withOpacity(0.3),
102 | completeColor: myBlue,
103 | completePercent: percentage,
104 | width: 8,
105 | ),
106 | ),
107 | );
108 | }
109 |
110 | Widget underlinedText(text) {
111 | double width = MediaQuery.of(context).size.width;
112 | return Padding(
113 | padding: const EdgeInsets.only(
114 | left: 25,
115 | ),
116 | child: Column(
117 | crossAxisAlignment: CrossAxisAlignment.start,
118 | children: [
119 | SizedBox(
120 | height: 20,
121 | ),
122 | Text(
123 | text,
124 | textScaleFactor: 0.9,
125 | style: TextStyle(
126 | letterSpacing: 1.1,
127 | color: Colors.black54,
128 | fontWeight: FontWeight.w700,
129 | fontFamily: 'Raleway',
130 | ),
131 | ),
132 | Divider(
133 | color: myBlue,
134 | thickness: 2,
135 | indent: width * 0.01,
136 | endIndent: width * 0.78,
137 | ),
138 | SizedBox(
139 | height: 10,
140 | ),
141 | ],
142 | ),
143 | );
144 | }
145 |
146 | @override
147 | Widget build(BuildContext context) {
148 | double width = MediaQuery.of(context).size.width;
149 | return SafeArea(
150 | child: Scaffold(
151 | backgroundColor: Colors.white,
152 | body: _currentStatus == RecordingStatus.Unset
153 | ? Center(
154 | child: CircularProgressIndicator(
155 | valueColor: AlwaysStoppedAnimation(
156 | myBlue,
157 | ),
158 | ),
159 | )
160 | : Column(
161 | children: [
162 | Expanded(
163 | child: SingleChildScrollView(
164 | child: Column(
165 | crossAxisAlignment: CrossAxisAlignment.start,
166 | mainAxisAlignment: MainAxisAlignment.spaceAround,
167 | children: [
168 | SizedBox(
169 | height: 20,
170 | ),
171 | Row(
172 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
173 | children: [
174 | Image.asset(
175 | 'assets/audio2.png',
176 | width: width * 0.55,
177 | ),
178 | getCirclePainter(),
179 | Text(
180 | _current.duration.inSeconds.toString() + " s",
181 | style: TextStyle(
182 | color: myBlue,
183 | fontWeight: FontWeight.w700,
184 | ),
185 | ),
186 | Container(),
187 | ],
188 | ),
189 | SizedBox(
190 | height: 40,
191 | ),
192 | timeKey != null ? getInputStream() : Container(),
193 | ],
194 | ),
195 | ),
196 | ),
197 | Row(
198 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
199 | children: [
200 | IconButton(
201 | icon: Icon(
202 | FontAwesomeIcons.stopCircle,
203 | color: myBlue,
204 | ),
205 | onPressed: _currentStatus != RecordingStatus.Unset
206 | ? _stop
207 | : null,
208 | ),
209 | Column(
210 | children: [
211 | _buildText(_currentStatus),
212 | SizedBox(
213 | height: 10,
214 | ),
215 | InkWell(
216 | onTap: micResponse,
217 | child: CircleAvatar(
218 | backgroundColor: myBlue,
219 | radius: 25,
220 | child: Icon(
221 | Icons.mic,
222 | color: Colors.white,
223 | ),
224 | ),
225 | ),
226 | SizedBox(
227 | height: 20,
228 | ),
229 | ],
230 | ),
231 | IconButton(
232 | icon: Icon(
233 | FontAwesomeIcons.signOutAlt,
234 | color: myBlue,
235 | ),
236 | onPressed: _logout,
237 | ),
238 | ],
239 | ),
240 | ],
241 | ),
242 | ),
243 | );
244 | }
245 |
246 | Widget getPlayer(text, url) {
247 | return Column(
248 | children: [
249 | underlinedText(text),
250 | PlayerWidget(
251 | url: url,
252 | ),
253 | ],
254 | );
255 | }
256 |
257 | Widget getInputStream() {
258 | return StreamBuilder(
259 | stream: FirebaseDatabase()
260 | .reference()
261 | .child(widget.userData.userEmail)
262 | .child(timeKey)
263 | .onValue,
264 | builder: (context, snap) {
265 | if (snap.hasData &&
266 | !snap.hasError &&
267 | snap.data.snapshot.value != null) {
268 | var data = snap.data.snapshot.value;
269 | return Column(
270 | children: [
271 | getPlayer("INPUT AUDIO", data["input"]),
272 | data["output"] == '-'
273 | ? Container()
274 | : getPlayer("FILTERED AUDIO", data["output"]),
275 | ],
276 | );
277 | } else
278 | return Center(
279 | child: Text(
280 | "Let's get started",
281 | textScaleFactor: 1.1,
282 | style: TextStyle(
283 | letterSpacing: 1.1,
284 | color: Colors.black54,
285 | fontWeight: FontWeight.w700,
286 | fontFamily: 'Raleway',
287 | ),
288 | ));
289 | },
290 | );
291 | }
292 |
293 | void micResponse() {
294 | switch (_currentStatus) {
295 | case RecordingStatus.Initialized:
296 | {
297 | _start();
298 | break;
299 | }
300 | case RecordingStatus.Recording:
301 | {
302 | _pause();
303 | break;
304 | }
305 | case RecordingStatus.Paused:
306 | {
307 | _resume();
308 | break;
309 | }
310 | case RecordingStatus.Stopped:
311 | {
312 | _init();
313 | break;
314 | }
315 | default:
316 | break;
317 | }
318 | }
319 |
320 | Future uploadInputSpeech(String _timeKey) async {
321 | DatabaseReference dbRef = FirebaseDatabase.instance.reference();
322 | final StorageReference storageRef = FirebaseStorage.instance.ref();
323 | io.File audioFile = io.File(_current.path);
324 |
325 | final StorageUploadTask uploadTask = storageRef
326 | .child("input_speech")
327 | .child(widget.userData.userEmail + _timeKey + ".wav")
328 | .putFile(audioFile);
329 | var audioUrl = await (await uploadTask.onComplete).ref.getDownloadURL();
330 | print(audioUrl);
331 |
332 | dbRef.child(widget.userData.userEmail).child(_timeKey).set({
333 | 'input': audioUrl,
334 | 'output': '-',
335 | }).whenComplete(() async {
336 | await runVoiceFilterBackend(
337 | widget.userData.userEmail, timeKey, audioUrl, widget.userData.refUrl);
338 | });
339 | }
340 |
341 | _stop() async {
342 | var result = await _recorder.stop();
343 | print("Stop recording: ${result.path}");
344 | print("Stop recording: ${result.duration}");
345 | File file = widget.localFileSystem.file(result.path);
346 | print("File length: ${await file.length()}");
347 |
348 | setState(() {
349 | _current = result;
350 | _currentStatus = _current.status;
351 | //timeKey = DateTime.now().toString().split('.')[0];
352 | timeKey = DateTime.now().millisecondsSinceEpoch.toString();
353 | });
354 |
355 | await uploadInputSpeech(timeKey);
356 | }
357 |
358 | Future _logout() async {
359 | await FirebaseAuthentication().signOut(context);
360 | }
361 |
362 | _init() async {
363 | try {
364 | if (await FlutterAudioRecorder.hasPermissions) {
365 | String customPath = '/audio_';
366 | io.Directory appDocDirectory;
367 | if (io.Platform.isIOS) {
368 | appDocDirectory = await getApplicationDocumentsDirectory();
369 | } else {
370 | appDocDirectory = await getExternalStorageDirectory();
371 | }
372 |
373 | // can add extension like ".mp4" ".wav" ".m4a" ".aac"
374 | customPath =
375 | appDocDirectory.path + customPath + DateTime.now().toString();
376 | //DateTime.now().millisecondsSinceEpoch.toString();
377 |
378 | _recorder =
379 | FlutterAudioRecorder(customPath, audioFormat: AudioFormat.WAV);
380 |
381 | await _recorder.initialized;
382 | // after initialization
383 | var current = await _recorder.current(channel: 0);
384 | print(current);
385 | // should be "Initialized", if all working fine
386 | setState(() {
387 | _current = current;
388 | _currentStatus = current.status;
389 | print(_currentStatus);
390 | });
391 | } else {
392 | Scaffold.of(context).showSnackBar(
393 | SnackBar(content: Text("You must accept permissions")));
394 | }
395 | } catch (e) {
396 | print(e);
397 | }
398 | }
399 |
400 | _start() async {
401 | try {
402 | await _recorder.start();
403 | var recording = await _recorder.current(channel: 0);
404 | setState(() {
405 | _current = recording;
406 | });
407 |
408 | const tick = const Duration(milliseconds: 50);
409 | Timer.periodic(tick, (Timer t) async {
410 | if (_currentStatus == RecordingStatus.Stopped) {
411 | t.cancel();
412 | }
413 |
414 | var current = await _recorder.current(channel: 0);
415 | setState(() {
416 | _current = current;
417 | _currentStatus = _current.status;
418 | });
419 | });
420 | } catch (e) {
421 | print(e);
422 | }
423 | }
424 |
425 | _resume() async {
426 | await _recorder.resume();
427 | setState(() {});
428 | }
429 |
430 | _pause() async {
431 | await _recorder.pause();
432 | setState(() {});
433 | }
434 |
435 | Widget _buildText(RecordingStatus status) {
436 | var text = "";
437 | switch (_currentStatus) {
438 | case RecordingStatus.Initialized:
439 | {
440 | text = 'Start';
441 | break;
442 | }
443 | case RecordingStatus.Recording:
444 | {
445 | text = 'Pause';
446 | break;
447 | }
448 | case RecordingStatus.Paused:
449 | {
450 | text = 'Resume';
451 | break;
452 | }
453 | case RecordingStatus.Stopped:
454 | {
455 | text = 'Initialize';
456 | break;
457 | }
458 | default:
459 | break;
460 | }
461 | return Text(
462 | text,
463 | style: TextStyle(
464 | color: myBlue,
465 | letterSpacing: 1.4,
466 | fontWeight: FontWeight.w900,
467 | fontFamily: 'Spartan',
468 | ),
469 | );
470 | }
471 | }
472 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/lib/screens/login_register_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:voicefilter/services/auth_service.dart';
3 | import 'package:voicefilter/widgets/dialogbox.dart';
4 | import 'package:voicefilter/utilities/constants.dart';
5 |
6 | class LoginRegisterScreen extends StatefulWidget {
7 | @override
8 | _LoginRegisterScreenState createState() => _LoginRegisterScreenState();
9 | }
10 |
11 | class _LoginRegisterScreenState extends State {
12 | DialogBox dialogBox = DialogBox();
13 |
14 | final _formKey = GlobalKey();
15 |
16 | bool login = true;
17 |
18 | String _email = "";
19 | String _password = "";
20 |
21 | @override
22 | Widget build(BuildContext context) {
23 | double width = MediaQuery.of(context).size.width;
24 | return Scaffold(
25 | backgroundColor: Colors.white,
26 | body: Form(
27 | key: _formKey,
28 | child: SingleChildScrollView(
29 | child: Column(
30 | mainAxisAlignment: MainAxisAlignment.center,
31 | crossAxisAlignment: CrossAxisAlignment.center,
32 | children: [
33 | SizedBox(
34 | height: 50,
35 | ),
36 | Image.asset(
37 | "assets/audio3.png",
38 | width: 0.6 * width,
39 | ),
40 | SizedBox(
41 | height: 15,
42 | ),
43 | Text(
44 | "Voice Filter",
45 | style: TextStyle(
46 | fontFamily: "Spartan",
47 | fontSize: 30,
48 | color: myBlue,
49 | letterSpacing: 1,
50 | fontWeight: FontWeight.w900,
51 | ),
52 | ),
53 | SizedBox(
54 | height: 20,
55 | ),
56 | Container(
57 | margin: EdgeInsets.symmetric(
58 | horizontal: 20,
59 | ),
60 | decoration: BoxDecoration(
61 | color: Colors.white,
62 | borderRadius: BorderRadius.circular(12.0),
63 | boxShadow: [
64 | BoxShadow(
65 | color: Colors.black12,
66 | offset: Offset(0, 5),
67 | blurRadius: 15,
68 | ),
69 | ]),
70 | child: Container(
71 | padding: EdgeInsets.only(left: 20, right: 20, bottom: 25),
72 | child: Column(
73 | children: screenInputs(),
74 | ),
75 | ),
76 | ),
77 | Container(
78 | child: Column(
79 | children: screenButtons(),
80 | ),
81 | ),
82 | ],
83 | ),
84 | ),
85 | ),
86 | );
87 | }
88 |
89 | List screenInputs() {
90 | return [
91 | TextFormField(
92 | style: TextStyle(
93 | color: Colors.black,
94 | fontFamily: 'Spartan',
95 | fontSize: 16,
96 | fontWeight: FontWeight.bold),
97 | decoration: InputDecoration(
98 | labelText: 'Email',
99 | labelStyle: TextStyle(
100 | color: Colors.grey[700],
101 | fontFamily: 'Montserrat',
102 | fontSize: 14,
103 | ),
104 | ),
105 | validator: (value) {
106 | return value.isEmpty ? 'Email is required' : null;
107 | },
108 | onSaved: (value) {
109 | return _email = value;
110 | },
111 | ),
112 | SizedBox(
113 | height: 10,
114 | ),
115 | TextFormField(
116 | style: TextStyle(
117 | color: Colors.black,
118 | fontFamily: 'Spartan',
119 | fontSize: 16,
120 | fontWeight: FontWeight.bold),
121 | decoration: InputDecoration(
122 | labelText: 'Password',
123 | labelStyle: TextStyle(
124 | color: Colors.grey[700],
125 | fontFamily: 'Montserrat',
126 | fontSize: 14,
127 | ),
128 | ),
129 | obscureText: true,
130 | validator: (value) {
131 | return value.isEmpty ? 'Password is required' : null;
132 | },
133 | onSaved: (value) {
134 | return _password = value;
135 | },
136 | ),
137 | ];
138 | }
139 |
140 | List screenButtons() {
141 | if (login) {
142 | return [
143 | SizedBox(
144 | height: 20,
145 | ),
146 | InkWell(
147 | onTap: submitForm,
148 | child: Container(
149 | width: 100,
150 | decoration: BoxDecoration(
151 | color: myBlue,
152 | borderRadius: BorderRadius.circular(6.0),
153 | ),
154 | child: Center(
155 | child: Padding(
156 | padding: EdgeInsets.symmetric(vertical: 10),
157 | child: Text(
158 | "LOGIN",
159 | style: TextStyle(
160 | fontFamily: 'Spartan',
161 | color: Colors.white,
162 | fontWeight: FontWeight.bold,
163 | letterSpacing: 1.5),
164 | ),
165 | ),
166 | ),
167 | ),
168 | ),
169 | FlatButton(
170 | child: Text(
171 | "Don't have an account? Register",
172 | style:
173 | TextStyle(color: myBlue, fontFamily: 'Poppins', fontSize: 12),
174 | ),
175 | onPressed: () {
176 | setState(() {
177 | login = !login;
178 | });
179 | },
180 | )
181 | ];
182 | } else {
183 | return [
184 | SizedBox(
185 | height: 20,
186 | ),
187 | InkWell(
188 | onTap: submitForm,
189 | child: Container(
190 | width: 120,
191 | decoration: BoxDecoration(
192 | color: myBlue,
193 | borderRadius: BorderRadius.circular(6.0),
194 | ),
195 | child: Center(
196 | child: Padding(
197 | padding: EdgeInsets.symmetric(vertical: 10),
198 | child: Text(
199 | "REGISTER",
200 | style: TextStyle(
201 | fontFamily: 'Spartan',
202 | color: Colors.white,
203 | fontWeight: FontWeight.bold,
204 | letterSpacing: 1.5,
205 | ),
206 | ),
207 | ),
208 | ),
209 | ),
210 | ),
211 | FlatButton(
212 | child: Text(
213 | "Don't have an account? Register",
214 | style: TextStyle(
215 | color: myBlue,
216 | fontFamily: 'Poppins',
217 | fontSize: 12,
218 | ),
219 | ),
220 | onPressed: () {
221 | setState(() {
222 | login = !login;
223 | });
224 | },
225 | )
226 | ];
227 | }
228 | }
229 |
230 | void submitForm() async {
231 | print("submi form");
232 | if (_formKey.currentState.validate()) {
233 | _formKey.currentState.save();
234 |
235 | try {
236 | if (login) {
237 | await FirebaseAuthentication().signIn(context, _email, _password);
238 | } else {
239 | await FirebaseAuthentication().signUp(context, _email, _password);
240 | }
241 | } catch (e) {
242 | print(e);
243 | DialogBox().information(context, "ERROR", e.toString());
244 | }
245 | }
246 | }
247 | }
248 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/lib/services/api.dart:
--------------------------------------------------------------------------------
1 | import 'package:http/http.dart' as http;
2 | import 'dart:convert';
3 |
4 | String postUrl = "< API KEY >";
5 |
6 | Future runVoiceFilterBackend(
7 | String userId,
8 | String timeId,
9 | String input,
10 | String ref,
11 | ) async {
12 | Map data = {
13 | 'user_id': userId,
14 | 'time_id': timeId,
15 | 'input_url': input,
16 | 'ref_url': ref,
17 | };
18 |
19 | //encode Map to JSON
20 | var body = json.encode(data);
21 | var response = await http.post(
22 | postUrl,
23 | body: body,
24 | );
25 | print("${response.statusCode}");
26 | }
27 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/lib/services/auth_manager.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:firebase_auth/firebase_auth.dart';
3 | import 'package:voicefilter/screens/filter_screen.dart';
4 | import 'package:voicefilter/screens/login_register_screen.dart';
5 | import 'package:voicefilter/utilities/constants.dart';
6 |
7 | class AuthManager extends StatefulWidget {
8 | @override
9 | _AuthManagerState createState() => _AuthManagerState();
10 | }
11 |
12 | class _AuthManagerState extends State {
13 | FirebaseUser user;
14 |
15 | Future getUserData() async {
16 | user = await FirebaseAuth.instance.currentUser();
17 | }
18 |
19 | @override
20 | Widget build(BuildContext context) {
21 | return FutureBuilder(
22 | future: getUserData(),
23 | builder: (context, futureSnapshot) {
24 | if (futureSnapshot.connectionState == ConnectionState.waiting) {
25 | return Scaffold(
26 | backgroundColor: Colors.white,
27 | body: Center(
28 | child: CircularProgressIndicator(
29 | valueColor: AlwaysStoppedAnimation(
30 | myBlue,
31 | ),
32 | ),
33 | ),
34 | );
35 | } else if (futureSnapshot.connectionState == ConnectionState.done &&
36 | user != null) {
37 | print('valid user');
38 | return FilterScreen();
39 | } else {
40 | print('No user');
41 | return LoginRegisterScreen();
42 | }
43 | },
44 | );
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/lib/services/auth_service.dart:
--------------------------------------------------------------------------------
1 | import 'package:firebase_auth/firebase_auth.dart';
2 | import 'package:firebase_database/firebase_database.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:voicefilter/screens/embedding_screen.dart';
5 | import 'package:voicefilter/screens/filter_screen.dart';
6 | import 'package:voicefilter/screens/login_register_screen.dart';
7 | import '../widgets/dialogBox.dart';
8 |
9 | class FirebaseAuthentication {
10 | Future signIn(context, email, password) async {
11 | try {
12 | AuthResult result =
13 | await FirebaseAuth.instance.signInWithEmailAndPassword(
14 | email: email,
15 | password: password,
16 | );
17 | print(result);
18 |
19 | DatabaseReference dbRef = FirebaseDatabase.instance
20 | .reference()
21 | .child(result.user.email.split('@')[0]);
22 | dbRef.once().then((DataSnapshot snapshot) {
23 | String val = snapshot.value["embedding"];
24 | if (val == '-') {
25 | Navigator.pushReplacement(
26 | context,
27 | MaterialPageRoute(
28 | builder: (context) => EmbeddingScreen(),
29 | ),
30 | );
31 | } else {
32 | Navigator.pushReplacement(
33 | context,
34 | MaterialPageRoute(
35 | builder: (context) => FilterScreen(),
36 | ),
37 | );
38 | }
39 | });
40 | } catch (e) {
41 | print("signin error:" + e.toString());
42 | DialogBox()
43 | .information(context, "ALERT", "Your login details are incorrect");
44 | }
45 | }
46 |
47 | Future signUp(context, email, password) async {
48 | try {
49 | AuthResult result =
50 | await FirebaseAuth.instance.createUserWithEmailAndPassword(
51 | email: email,
52 | password: password,
53 | );
54 | print(result);
55 |
56 | DatabaseReference dbRef = FirebaseDatabase.instance.reference();
57 | dbRef.child(result.user.email.split('@')[0]).set({
58 | 'embedding': '-',
59 | });
60 |
61 | Navigator.pushReplacement(
62 | context,
63 | MaterialPageRoute(
64 | builder: (context) => EmbeddingScreen(),
65 | ),
66 | );
67 | } catch (e) {
68 | DialogBox().information(context, "ERROR", e.toString());
69 | print(e);
70 | return e;
71 | }
72 | }
73 |
74 | Future signOut(context) async {
75 | await FirebaseAuth.instance.signOut().then(
76 | (value) => Navigator.pushReplacement(
77 | context,
78 | MaterialPageRoute(
79 | builder: (context) => LoginRegisterScreen(),
80 | ),
81 | ),
82 | );
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/lib/utilities/constants.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | Color myBlue = Color(0xff536DFE);
4 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/lib/widgets/custom_painter.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 | import 'package:flutter/material.dart';
3 | import 'dart:math';
4 |
5 | class CirclePainter extends CustomPainter {
6 | Color lineColor;
7 | Color completeColor;
8 | double completePercent;
9 | double width;
10 | CirclePainter(
11 | {this.lineColor, this.completeColor, this.completePercent, this.width});
12 | @override
13 | void paint(Canvas canvas, Size size) {
14 | Paint line = new Paint()
15 | ..color = lineColor
16 | ..strokeCap = StrokeCap.round
17 | ..style = PaintingStyle.stroke
18 | ..strokeWidth = width;
19 | Paint complete = new Paint()
20 | ..color = completeColor
21 | ..strokeCap = StrokeCap.round
22 | ..style = PaintingStyle.stroke
23 | ..strokeWidth = width;
24 | Offset center = new Offset(size.width / 2, size.height / 2);
25 | double radius = min(size.width / 2, size.height / 2);
26 | canvas.drawCircle(center, radius, line);
27 | double arcAngle = 2 * pi * (completePercent / 100);
28 | canvas.drawArc(new Rect.fromCircle(center: center, radius: radius), -pi / 2,
29 | arcAngle, false, complete);
30 | }
31 |
32 | @override
33 | bool shouldRepaint(CustomPainter oldDelegate) {
34 | return true;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/lib/widgets/dialogbox.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:font_awesome_flutter/font_awesome_flutter.dart';
3 | import 'package:voicefilter/utilities/constants.dart';
4 |
5 | class DialogBox {
6 | information(BuildContext context, String title, String desc) {
7 | print(
8 | "dialog : " + Theme.of(context).primaryColor.toString(),
9 | );
10 | return showDialog(
11 | context: context,
12 | barrierDismissible: true,
13 | builder: (BuildContext context) {
14 | return AlertDialog(
15 | backgroundColor: Colors.white,
16 | title: Text(
17 | title,
18 | style: TextStyle(
19 | color: myBlue,
20 | fontSize: 30,
21 | fontWeight: FontWeight.bold,
22 | letterSpacing: 0.3,
23 | ),
24 | ),
25 | content: SingleChildScrollView(
26 | child: ListBody(
27 | children: [
28 | Text(
29 | desc,
30 | style: TextStyle(
31 | fontSize: 12,
32 | color: Colors.black54,
33 | fontWeight: FontWeight.w600,
34 | letterSpacing: 1.2,
35 | ),
36 | ),
37 | ],
38 | ),
39 | ),
40 | actions: [
41 | FlatButton(
42 | onPressed: () {
43 | return Navigator.pop(context);
44 | },
45 | child: FaIcon(
46 | FontAwesomeIcons.checkCircle,
47 | color: myBlue,
48 | ),
49 | ),
50 | ],
51 | );
52 | });
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/lib/widgets/player_widget.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'package:audioplayers/audioplayers.dart';
3 | import 'package:flutter/foundation.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:voicefilter/utilities/constants.dart';
6 |
7 | enum PlayerState { stopped, playing, paused }
8 | enum PlayingRouteState { speakers, earpiece }
9 |
10 | class PlayerWidget extends StatefulWidget {
11 | final String url;
12 | final PlayerMode mode;
13 |
14 | PlayerWidget({
15 | Key key,
16 | @required this.url,
17 | this.mode = PlayerMode.MEDIA_PLAYER,
18 | }) : super(key: key);
19 |
20 | @override
21 | State createState() {
22 | return _PlayerWidgetState(url, mode);
23 | }
24 | }
25 |
26 | class _PlayerWidgetState extends State {
27 | String url;
28 | PlayerMode mode;
29 |
30 | AudioPlayer _audioPlayer;
31 | AudioPlayerState _audioPlayerState;
32 | Duration _duration;
33 | Duration _position;
34 |
35 | PlayerState _playerState = PlayerState.stopped;
36 | PlayingRouteState _playingRouteState = PlayingRouteState.speakers;
37 | StreamSubscription _durationSubscription;
38 | StreamSubscription _positionSubscription;
39 | StreamSubscription _playerCompleteSubscription;
40 | StreamSubscription _playerErrorSubscription;
41 | StreamSubscription _playerStateSubscription;
42 |
43 | get _isPlaying => _playerState == PlayerState.playing;
44 | get _isPaused => _playerState == PlayerState.paused;
45 | get _durationText => _duration?.toString()?.split('.')?.first ?? '';
46 | get _positionText => _position?.toString()?.split('.')?.first ?? '';
47 |
48 | get _isPlayingThroughEarpiece =>
49 | _playingRouteState == PlayingRouteState.earpiece;
50 |
51 | _PlayerWidgetState(this.url, this.mode);
52 |
53 | @override
54 | void initState() {
55 | super.initState();
56 | _initAudioPlayer();
57 | }
58 |
59 | @override
60 | void dispose() {
61 | _audioPlayer.dispose();
62 | _durationSubscription?.cancel();
63 | _positionSubscription?.cancel();
64 | _playerCompleteSubscription?.cancel();
65 | _playerErrorSubscription?.cancel();
66 | _playerStateSubscription?.cancel();
67 | super.dispose();
68 | }
69 |
70 | @override
71 | Widget build(BuildContext context) {
72 | double width = MediaQuery.of(context).size.width;
73 | return Container(
74 | padding: EdgeInsets.symmetric(
75 | vertical: 10,
76 | horizontal: 10,
77 | ),
78 | decoration: BoxDecoration(
79 | borderRadius: BorderRadius.circular(10),
80 | color: Colors.white,
81 | boxShadow: [
82 | BoxShadow(
83 | color: Colors.black.withOpacity(.3),
84 | blurRadius: 2.0,
85 | )
86 | ]),
87 | margin: EdgeInsets.symmetric(
88 | horizontal: width * 0.06,
89 | vertical: 3,
90 | ),
91 | child: Column(
92 | mainAxisSize: MainAxisSize.min,
93 | children: [
94 | Row(
95 | mainAxisSize: MainAxisSize.min,
96 | children: [
97 | IconButton(
98 | key: Key('play_button'),
99 | onPressed: _isPlaying ? null : () => _play(),
100 | iconSize: 32,
101 | icon: Icon(Icons.play_arrow),
102 | color: myBlue,
103 | ),
104 | IconButton(
105 | key: Key('pause_button'),
106 | onPressed: _isPlaying ? () => _pause() : null,
107 | iconSize: 32,
108 | icon: Icon(Icons.pause),
109 | color: myBlue,
110 | ),
111 | IconButton(
112 | key: Key('stop_button'),
113 | onPressed: _isPlaying || _isPaused ? () => _stop() : null,
114 | iconSize: 32,
115 | icon: Icon(Icons.stop),
116 | color: myBlue,
117 | ),
118 | ],
119 | ),
120 | Column(
121 | mainAxisSize: MainAxisSize.min,
122 | children: [
123 | Padding(
124 | padding: EdgeInsets.all(8),
125 | child: Stack(
126 | children: [
127 | Slider(
128 | activeColor: myBlue,
129 | inactiveColor: Colors.black38,
130 | onChanged: (v) {
131 | final position = v * _duration.inMilliseconds;
132 | _audioPlayer
133 | .seek(Duration(milliseconds: position.round()));
134 | },
135 | value: (_position != null &&
136 | _duration != null &&
137 | _position.inMilliseconds > 0 &&
138 | _position.inMilliseconds <
139 | _duration.inMilliseconds)
140 | ? _position.inMilliseconds / _duration.inMilliseconds
141 | : 0.0,
142 | ),
143 | ],
144 | ),
145 | ),
146 | Text(
147 | _position != null
148 | ? '${_positionText ?? ''} / ${_durationText ?? ''}'
149 | : _duration != null ? _durationText : '',
150 | style: TextStyle(
151 | fontSize: 12,
152 | letterSpacing: 1,
153 | color: myBlue,
154 | fontFamily: 'Montserrat',
155 | ),
156 | ),
157 | ],
158 | ),
159 | ],
160 | ),
161 | );
162 | }
163 |
164 | void _initAudioPlayer() {
165 | _audioPlayer = AudioPlayer(mode: mode);
166 |
167 | _durationSubscription = _audioPlayer.onDurationChanged.listen((duration) {
168 | setState(() => _duration = duration);
169 |
170 | //implemented for iOS, waiting for android impl
171 |
172 | if (Theme.of(context).platform == TargetPlatform.iOS) {
173 | // (Optional) listen for notification updates in the background
174 | _audioPlayer.startHeadlessService();
175 |
176 | // set at least title to see the notification bar on ios.
177 | _audioPlayer.setNotification(
178 | title: 'App Name',
179 | artist: 'Artist or blank',
180 | albumTitle: 'Name or blank',
181 | imageUrl: 'url or blank',
182 | forwardSkipInterval: const Duration(seconds: 30), // default is 30s
183 | backwardSkipInterval: const Duration(seconds: 30), // default is 30s
184 | duration: duration,
185 | elapsedTime: Duration(seconds: 0));
186 | }
187 | });
188 |
189 | _positionSubscription =
190 | _audioPlayer.onAudioPositionChanged.listen((p) => setState(() {
191 | _position = p;
192 | }));
193 |
194 | _playerCompleteSubscription =
195 | _audioPlayer.onPlayerCompletion.listen((event) {
196 | _onComplete();
197 | setState(() {
198 | _position = _duration;
199 | });
200 | });
201 |
202 | _playerErrorSubscription = _audioPlayer.onPlayerError.listen((msg) {
203 | print('audioPlayer error : $msg');
204 | setState(() {
205 | _playerState = PlayerState.stopped;
206 | _duration = Duration(seconds: 0);
207 | _position = Duration(seconds: 0);
208 | });
209 | });
210 |
211 | _audioPlayer.onPlayerStateChanged.listen((state) {
212 | if (!mounted) return;
213 | setState(() {
214 | _audioPlayerState = state;
215 | });
216 | });
217 |
218 | _audioPlayer.onNotificationPlayerStateChanged.listen((state) {
219 | if (!mounted) return;
220 | setState(() => _audioPlayerState = state);
221 | });
222 |
223 | _playingRouteState = PlayingRouteState.speakers;
224 | }
225 |
226 | Future _play() async {
227 | final playPosition = (_position != null &&
228 | _duration != null &&
229 | _position.inMilliseconds > 0 &&
230 | _position.inMilliseconds < _duration.inMilliseconds)
231 | ? _position
232 | : null;
233 |
234 | print(url);
235 |
236 | final result = await _audioPlayer.play(
237 | url,
238 | position: playPosition,
239 | );
240 | if (result == 1) setState(() => _playerState = PlayerState.playing);
241 |
242 | // default playback rate is 1.0
243 | // this should be called after _audioPlayer.play() or _audioPlayer.resume()
244 | // this can also be called everytime the user wants to change playback rate in the UI
245 | _audioPlayer.setPlaybackRate(playbackRate: 1.0);
246 |
247 | return result;
248 | }
249 |
250 | Future _pause() async {
251 | final result = await _audioPlayer.pause();
252 | if (result == 1) setState(() => _playerState = PlayerState.paused);
253 | return result;
254 | }
255 |
256 | Future _earpieceOrSpeakersToggle() async {
257 | final result = await _audioPlayer.earpieceOrSpeakersToggle();
258 | if (result == 1)
259 | setState(() => _playingRouteState =
260 | _playingRouteState == PlayingRouteState.speakers
261 | ? PlayingRouteState.earpiece
262 | : PlayingRouteState.speakers);
263 | return result;
264 | }
265 |
266 | Future _stop() async {
267 | final result = await _audioPlayer.stop();
268 | if (result == 1) {
269 | setState(() {
270 | _playerState = PlayerState.stopped;
271 | _position = Duration();
272 | });
273 | }
274 | return result;
275 | }
276 |
277 | void _onComplete() {
278 | setState(() => _playerState = PlayerState.stopped);
279 | }
280 | }
281 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: voicefilter
2 | description: A new Flutter project.
3 |
4 | # The following line prevents the package from being accidentally published to
5 | # pub.dev using `pub publish`. This is preferred for private packages.
6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev
7 |
8 | # The following defines the version and build number for your application.
9 | # A version number is three numbers separated by dots, like 1.2.43
10 | # followed by an optional build number separated by a +.
11 | # Both the version and the builder number may be overridden in flutter
12 | # build by specifying --build-name and --build-number, respectively.
13 | # In Android, build-name is used as versionName while build-number used as versionCode.
14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
16 | # Read more about iOS versioning at
17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
18 | version: 1.0.0+1
19 |
20 | environment:
21 | sdk: ">=2.7.0 <3.0.0"
22 |
23 | dependencies:
24 | flutter:
25 | sdk: flutter
26 | permission_handler: ^5.0.1+1
27 | flutter_audio_recorder: ^0.5.5
28 | file: ^5.2.1
29 | audioplayers: ^0.15.1
30 | firebase_storage: ^3.1.6
31 | firebase_auth: ^0.16.1
32 | cloud_firestore: ^0.13.7
33 | firebase_database: ^3.1.6
34 | font_awesome_flutter: ^8.8.1
35 | dio: ^3.0.9
36 | http: ^0.12.1
37 |
38 | # The following adds the Cupertino Icons font to your application.
39 | # Use with the CupertinoIcons class for iOS style icons.
40 | cupertino_icons: ^0.1.3
41 |
42 | dev_dependencies:
43 | flutter_test:
44 | sdk: flutter
45 |
46 | # For information on the generic Dart part of this file, see the
47 | # following page: https://dart.dev/tools/pub/pubspec
48 |
49 | # The following section is specific to Flutter.
50 | flutter:
51 |
52 | # The following line ensures that the Material Icons font is
53 | # included with your application, so that you can use the icons in
54 | # the material Icons class.
55 | uses-material-design: true
56 |
57 | # To add assets to your application, add an assets section, like this:
58 | assets:
59 | - assets/audio1.png
60 | - assets/audio2.png
61 | - assets/audio3.png
62 |
63 | # An image asset can refer to one or more resolution-specific "variants", see
64 | # https://flutter.dev/assets-and-images/#resolution-aware.
65 |
66 | # For details regarding adding assets from package dependencies, see
67 | # https://flutter.dev/assets-and-images/#from-packages
68 |
69 | # To add custom fonts to your application, add a fonts section here,
70 | # in this "flutter" section. Each entry in this list should have a
71 | # "family" key with the font family name, and a "fonts" key with a
72 | # list giving the asset and other descriptors for the font. For
73 | # example:
74 | fonts:
75 | - family: Montserrat
76 | fonts:
77 | - asset: fonts/Montserrat-Regular.ttf
78 | - family: Raleway
79 | fonts:
80 | - asset: fonts/Raleway-Regular.ttf
81 | - family: Spartan
82 | fonts:
83 | - asset: fonts/Spartan-Regular.ttf
84 | - family: Poppins
85 | fonts:
86 | - asset: fonts/Poppins-Regular.ttf
87 | #
88 | # For details regarding fonts from package dependencies,
89 | # see https://flutter.dev/custom-fonts/#from-packages
90 |
--------------------------------------------------------------------------------
/flutter app/voicefilter/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility that Flutter provides. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_test/flutter_test.dart';
10 |
11 | import 'package:voicefilter/main.dart';
12 |
13 | void main() {
14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(MyApp());
17 |
18 | // Verify that our counter starts at 0.
19 | expect(find.text('0'), findsOneWidget);
20 | expect(find.text('1'), findsNothing);
21 |
22 | // Tap the '+' icon and trigger a frame.
23 | await tester.tap(find.byIcon(Icons.add));
24 | await tester.pump();
25 |
26 | // Verify that our counter has incremented.
27 | expect(find.text('0'), findsNothing);
28 | expect(find.text('1'), findsOneWidget);
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/model/model.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import tensorflow as tf
3 | from tensorflow.keras import Model
4 | from tensorflow.keras.layers import Multiply, ZeroPadding2D, concatenate, Conv2D, Input, Dense, Reshape, BatchNormalization, Activation, LSTM, Bidirectional, Lambda
5 | from Audio import Audio
6 | from HyperParams import HyperParams
7 |
8 | hyper_params = HyperParams()
9 | audio = Audio(hyper_params)
10 | #input dims for model [ T_dim, num_freq ]
11 | T_dim = 301
12 | num_freq = hyper_params.num_freq
13 | emb_dim = hyper_params.embedder_emb_dim
14 | lstm_dim = hyper_params.model_lstm_dim
15 | fc1_dim = hyper_params.model_fc1_dim
16 | fc2_dim = hyper_params.model_fc2_dim #num_freq
17 | batch_size = 8
18 |
19 | def get_model():
20 | dvec_inp = Input(shape=[emb_dim],name="dvec")
21 | input_spec = Input(shape=[T_dim,num_freq],name="input_spec")
22 | x = Reshape((T_dim,num_freq,1))(input_spec)
23 |
24 | # cnn
25 |
26 | #cnn1
27 | x = ZeroPadding2D(((0,0), (3,3)))(x)
28 | x = Conv2D(filters=64, kernel_size=[1,7], dilation_rate=[1, 1])(x)
29 | x = BatchNormalization()(x)
30 | x = Activation('relu')(x)
31 | #cnn2
32 | x = ZeroPadding2D(((3,3), (0,0)))(x)
33 | x = Conv2D(filters=64, kernel_size=[7,1], dilation_rate=[1, 1])(x)
34 | x = BatchNormalization()(x)
35 | x = Activation('relu')(x)
36 | #cnn3
37 | x = ZeroPadding2D(((2,2), (2,2)))(x)
38 | x = Conv2D(filters=64, kernel_size=[5,5], dilation_rate=[1, 1])(x)
39 | x = BatchNormalization()(x)
40 | x = Activation('relu')(x)
41 | #cnn4
42 | x = ZeroPadding2D(((4,4), (2,2)))(x)
43 | x = Conv2D(filters=64, kernel_size=[5,5], dilation_rate=[2, 1])(x)
44 | x = BatchNormalization()(x)
45 | x = Activation('relu')(x)
46 | #cnn5
47 | x = ZeroPadding2D(((8,8), (2,2)))(x)
48 | x = Conv2D(filters=64, kernel_size=[5,5], dilation_rate=[4, 1])(x)
49 | x = BatchNormalization()(x)
50 | x = Activation('relu')(x)
51 | #cnn6
52 | x = ZeroPadding2D(((16,16), (2,2)))(x)
53 | x = Conv2D(filters=64, kernel_size=[5,5], dilation_rate=[8, 1])(x)
54 | x = BatchNormalization()(x)
55 | x = Activation('relu')(x)
56 | #cnn7
57 | x = ZeroPadding2D(((32,32), (2,2)))(x)
58 | x = Conv2D(filters=64, kernel_size=[5,5], dilation_rate=[16, 1])(x)
59 | x = BatchNormalization()(x)
60 | x = Activation('relu')(x)
61 | #cnn8
62 | x = Conv2D(filters=8, kernel_size=[1,1], dilation_rate=[1, 1])(x)
63 | x = BatchNormalization()(x)
64 | x = Activation('relu')(x)
65 |
66 | x = Reshape((x.shape[1],x.shape[2]*x.shape[3]))(x) #else use -1 as last arg
67 | #x = tf.reshape(x, [x.shape[0],x.shape[1],-1])
68 |
69 | dvec = Lambda(lambda a : tf.expand_dims(a,1))(dvec_inp)
70 | dvec = Lambda(lambda a : tf.repeat(a,repeats =x.shape[1],axis =1))(dvec)
71 | #dvec= tf.expand_dims(dvec_inp,1)
72 | #dvec= tf.repeat(dvec,repeats =x.shape[1],axis =1)
73 |
74 | x = concatenate([x,dvec],-1)
75 | #x= tf.concat([x,dvec],-1)
76 |
77 | #lstm
78 | x = Bidirectional(LSTM(lstm_dim,return_sequences=True))(x)
79 |
80 | #fc1
81 | x = Dense(fc1_dim,activation ="relu")(x)
82 | #fc2
83 | mask = Dense(fc2_dim,activation ="sigmoid",name="mask")(x) #soft mask
84 |
85 | #element-wise
86 | output = Multiply()([input_spec,mask])
87 |
88 | model = Model(inputs=[input_spec,dvec_inp], outputs=output)
89 |
90 | return model
--------------------------------------------------------------------------------
/model/sequence_generator.py:
--------------------------------------------------------------------------------
1 | from tensorflow.keras.utils import Sequence
2 | import numpy as np
3 | import os
4 |
5 | dataset_path = os.path.join('drive','My Drive','LibriSpeech Dataset')
6 | path = {}
7 | path['dev'] = os.path.join(dataset_path,'LibriSpeech Dev Dataset')
8 | path['test'] = os.path.join(dataset_path,'LibriSpeech Test Dataset')
9 | path['train'] = os.path.join(dataset_path ,'LibriSpeech Train Dataset')
10 |
11 |
12 | class data_generator(Sequence):
13 | def __init__(self, fraction_sizes , batch_size):
14 | self.batch_size = batch_size
15 | self.fraction_sizes = fraction_sizes
16 | self.num_fractions = len(fraction_sizes)
17 | self.num_samples = sum(self.fraction_sizes)
18 | self.pos = 0
19 | self.cur_fraction = 0
20 | self.input_spec=None
21 | self.output_spec=None
22 | self.dvec=None
23 | def __len__(self):
24 | self.num_batches = 0
25 | for i in range(self.num_fractions):
26 | self.num_batches += (self.fraction_sizes[i]+self.batch_size-1)//self.batch_size
27 | print("len ",self.num_batches)
28 | return self.num_batches
29 | def __getitem__(self,batch_index):
30 | start_pos = self.pos
31 | end_pos = start_pos + self.batch_size
32 | if end_pos > self.fraction_sizes[self.cur_fraction]:
33 | end_pos = self.fraction_sizes[self.cur_fraction]
34 | if start_pos == 0 :
35 | print("loading new data")
36 | if self.input_spec is not None:
37 | print("de allocating old space")
38 | del self.input_spec
39 | del self.output_spec
40 | del self.dvec
41 | indices = np.random.permutation(self.fraction_sizes[self.cur_fraction])
42 | self.input_spec = np.load(os.path.join(dataset_path,'PreLoad Training Dataset','fraction_'+str(self.cur_fraction),'input_spec.npy'))[indices]
43 | self.output_spec = np.load(os.path.join(dataset_path,'PreLoad Training Dataset','fraction_'+str(self.cur_fraction),'output_spec.npy'))[indices]
44 | self.dvec = np.load(os.path.join(dataset_path,'PreLoad Training Dataset','fraction_'+str(self.cur_fraction),'dvec.npy'))[indices]
45 | print("new data loaded ")
46 | if end_pos == self.fraction_sizes[self.cur_fraction]:
47 | self.cur_fraction += 1
48 | if self.cur_fraction == self.num_fractions:
49 | self.cur_fraction = 0
50 | self.pos = 0
51 | else :
52 | self.pos = end_pos
53 | input_spec_batch = self.input_spec[start_pos:end_pos]
54 | dvector_batch = self.dvec[start_pos:end_pos]
55 | output_spec_batch = self.output_spec[start_pos:end_pos]
56 | return ({'input_spec':input_spec_batch, 'dvec': dvector_batch}, output_spec_batch)
57 | def on_epoch_end(self):
58 | self.pos = 0
59 | self.cur_fraction = 0
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | tensorflow==2.3.0
2 | librosa==0.6.3
3 | numpy==1.18.5
4 | pandas==1.0.5
5 | torch==1.6.0+cu101
6 | matplotlib==3.2.2
7 | mir_eval==0.6
8 | tqdm==4.41.1
--------------------------------------------------------------------------------
/train_test/testing.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | import numpy as np
3 | from mir_eval.separation import bss_eval_sources
4 | from tqdm import tqdm
5 | import os
6 | import matplotlib.pyplot as plt
7 |
8 | from model import get_model
9 | from HyperParams import HyperParams
10 | from Audio import Audio
11 |
12 | hyper_params = HyperParams
13 | audio = Audio(hyper_params)
14 | batch_size = 8
15 |
16 | dataset_path = os.path.join('drive','My Drive','LibriSpeech Dataset')
17 | path = {}
18 | path['dev'] = os.path.join(dataset_path,'LibriSpeech Dev Dataset')
19 | path['test'] = os.path.join(dataset_path,'LibriSpeech Test Dataset')
20 | path['train'] = os.path.join(dataset_path ,'LibriSpeech Train Dataset')
21 | dataset = 'dev'
22 |
23 | input_spec = np.load(os.path.join(path[dataset],'input_spec.npy'))
24 | input_phase = np.load(os.path.join(path[dataset],'input_phase.npy'))
25 | output_spec = np.load(os.path.join(path[dataset],'output_spec.npy'))
26 | output_phase = np.load(os.path.join(path[dataset],'output_phase.npy'))
27 | dvec = np.load(os.path.join(path[dataset],'dvec.npy'))
28 |
29 | target_waves = []
30 | for i in tqdm(range(output_spec.shape[0])):
31 | target_waves.append(audio.spec2wave(output_spec[i], output_phase[i]))
32 | val_loss = []
33 | val_sdr = []
34 |
35 | model = get_model()
36 | model.compile(optimizer='adam', loss='mse')
37 |
38 | def compute_loss_sdr(weights_path):
39 | model.load_weights(weights_path)
40 | predict_spec = model.predict(x={'input_spec':input_spec,'dvec':dvec} , batch_size = batch_size, verbose = 1)
41 | val_loss.append(np.mean(np.square(output_spec - predict_spec)))
42 | sdr=[]
43 | for i in tqdm(range(predict_spec.shape[0])):
44 | #true_wave = audio.spec2wave(np.load(df_dev['output_spec_path'][i]),np.load(df_dev['output_phase_path'][i]))
45 | predict_wave = audio.spec2wave(predict_spec[i], input_phase[i])
46 | sdr.append(bss_eval_sources(target_waves[i], predict_wave, False)[0][0])
47 | val_sdr.append(np.median(np.array(sdr)))
48 |
49 | ### config ###
50 | start_epochs = 1
51 | end_epochs = 6
52 |
53 | for i in range(start_epochs,end_epochs):
54 | weights_path = os.path.join(dataset_path,'Model weights','weights_epoch%04d.h5'%i)
55 | compute_loss_sdr(weights_path)
56 | print()
57 | print(val_loss)
58 | print(val_sdr)
59 | np.save(os.path.join(dataset_path,'val_loss_total_epochs%04d'%(end_epochs-1)),np.array(val_loss))
60 | np.save(os.path.join(dataset_path,'val_sdr_total_epochs%04d'%(end_epochs-1)),np.array(val_sdr))
61 |
62 | loss = np.load(os.path.join(path[dataset],'training_loss_total_epochs%04d.npy'%(end_epochs-1)))
63 |
64 | fig , axis = plt.subplots(1,1,figsize = (9,6))
65 | axis.plot(np.array(range(1,len(loss)+1)),loss,label="training loss")
66 | axis.plot(5*np.array(range(len(val_loss))),val_loss,label="val loss")
67 | axis.legend()
68 | plt.xticks(np.array(range(len(loss)+1)))
69 | plt.xlabel('epoch')
70 | plt.ylabel('loss')
71 | plt.title('Loss')
72 | plt.show()
73 | fig.savefig('loss.png')
74 |
75 | fig , axis = plt.subplots(1,1,figsize = (6,6))
76 | axis.plot(5*np.array(range(len(val_sdr))), val_sdr, label = "median sdr on val set")
77 | plt.xlabel('epoch')
78 | plt.ylabel('median sdr')
79 | plt.title('SDR on dev set')
80 | plt.show()
81 | fig.savefig('sdr.png')
--------------------------------------------------------------------------------
/train_test/train.py:
--------------------------------------------------------------------------------
1 | import os
2 | import pandas as pd
3 | import numpy as np
4 | from tensorflow.keras.callbacks import Callback
5 | from tensorflow.keras.callbacks import ModelCheckpoint
6 | from tqdm import tqdm
7 |
8 | from Audio import Audio
9 | from HyperParams import HyperParams
10 | from model import get_model
11 | from sequence_generator import data_generator
12 |
13 | hyper_params = HyperParams()
14 | audio = Audio(hyper_params)
15 | dataset_path = os.path.join('drive','My Drive','LibriSpeech Dataset')
16 | path = {}
17 | path['dev'] = os.path.join(dataset_path,'LibriSpeech Dev Dataset')
18 | path['test'] = os.path.join(dataset_path,'LibriSpeech Test Dataset')
19 | path['train'] = os.path.join(dataset_path ,'LibriSpeech Train Dataset')
20 |
21 | model = get_model()
22 | model.summary()
23 |
24 | model.compile(optimizer='adam', loss='mse')
25 |
26 | ### execute just once ###
27 | model.save_weights(os.path.join(dataset_path,'Model weights','weights_epoch0000.h5'))
28 |
29 | dataset_train = 'train'
30 | df_train = pd.read_csv(os.path.join(path[dataset_train],'data_frame.csv'))
31 | num_samples = df_train.shape[0]
32 | batch_size = 8
33 |
34 | num_fractions = 8
35 | fraction_sizes = num_fractions * [ num_samples//num_fractions ]
36 | for i in range(num_samples%num_fractions):
37 | fraction_sizes[i]+=1
38 | print(fraction_sizes)
39 |
40 | steps_per_epoch = 0
41 | for i in range(num_fractions):
42 | steps_per_epoch += (fraction_sizes[i]+batch_size-1)//batch_size
43 | print(steps_per_epoch)
44 |
45 | gen_train = data_generator(fraction_sizes, batch_size)
46 |
47 | model_checkpoint_callback = ModelCheckpoint(
48 | os.path.join(dataset_path,'Model weights','weights_epoch{epoch:04d}.h5'),save_weights_only=True)
49 |
50 | ### config ###
51 | initial_epoch = 0
52 | epochs = 20
53 |
54 | hist = model.fit(gen_train, epochs=epochs, verbose=1, steps_per_epoch = 2, shuffle=False,
55 | callbacks=[model_checkpoint_callback
56 | # myCallback()
57 | ]
58 | )
59 |
60 | loss = hist.history['loss']
61 | np.save(os.path.join(dataset_path,'training_loss_total_epochs%04d'%epochs),np.array(loss))
62 |
--------------------------------------------------------------------------------