俺、サービス売って家買うんだ

Swift, Kotlin, Vue.js, 統計, GCP / このペースで作ってればいつか2-3億で売れるのがポっと出来るんじゃなかろうか

iOS AVAudioSession周りの覚書

f:id:ie-kau:20190711075808p:plain

音声 x 外部ヘッドセット周りで嵌ったのでメモメモ。φ(・

基礎知識

44,100 Hz

デジタルオーディオにおける一般的なサンプリング周波数。アナログオーディオは一秒間に441000回標本化される。

ハード側

iPhoneのスピーカー

  • 通話用スピーカー
    • 上についているやつ
  • 内蔵スピーカー
    • 右側がスピーカー、左側がマイク

BluetoothHFPとは

Bluetooth Hands-Free Profile の略。

携帯電話 - ヘッドセット間などで用いられる、電話の発着信や通話を行なうためのプロファイル。

アプリケーション側

AVAudioSessionとは?

OS(及びハードウェア)とアプリケーションの仲介を行うオブジェクト。
デフォルトでは以下の設定がされている。

  • 再生はサポートされているが、録音はサポートされていない
  • マナーモードにするとアプリで再生されている音はすべて無音になる (iOSのみ)
  • デバイスがロックされたら音が止まる (iOSのみ)
  • アプリがオーディオを再生し始めたらバックグラウンドで流れている音楽を止める

デフォルトの振る舞いを変更するには audio session category を変更する必要がある。

Audio Session Category とは?

オーディオの振る舞いを定義する Audio Session プロパティ。
playback(再生)だけとか、record(録音)だけとか、 playAndRecord(再生と録音)とか。 さらにsession modeを設定することで、より洗練した音質を提供できる。

Audio Session Mode

category がベースとなる振る舞いを設定するのに対して、 mode は専門的にするために使うカテゴリーの振る舞いを専門化できる。 例えば videoChat は playAndRecord, recod カテゴリといっしょにつかい、音声に対するトーンイコライザの最適化を提供する。また許容されるオーディオルートをビデオチャットに適したものだけに削減する。

※オーディオルート => どこから音を出すかとか、ヘッドフォンとかBluetoothとか。

オーディオルートの変更を検知する

オーディオのアウトプットを外付けスピーカーからBluetoothに変えた場合などを検知する場合は AVAudioSessionRouteChangeNotification を利用すればよい。

(例) 内蔵スピーカーからBluetoothに変わったときの出力

let center = NotificationCenter.default
center.addObserver(self, selector: #selector(didAudioSessionRouteChanged(_:)), name: AVAudioSession.routeChangeNotification, object: nil)
@objc func audioSessionRouteChanged(_ notification: Notification) {
      guard let userInfo = notification.userInfo,
          let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt,
          let reason = AVAudioSession.RouteChangeReason(rawValue:reasonValue) else {
              return
      }

      let session: AVAudioSession = AVAudioSession.sharedInstance()
      print(session.sampleRate)  // Bluetoothにイヤフォンにした場合サンプルレートが変わってるはず

      switch reason {
      case .newDeviceAvailable:
          print("newDeviceAvailable")

          for output in session.currentRoute.outputs {
              print(output.portType)  // BluetoothHFP
              print(output.portName)  // 製品名 or AirPodsなら自分で登録した名前
          }

      case .oldDeviceUnavailable:
          print("oldDeviceUnavailable")

      case .unknown:
          print("unkonw")

      case .categoryChange:
          print("categoryChange")

      case .override:
          print("override")

      case .wakeFromSleep:
          print("wakeFromSleep")

      case .noSuitableRouteForCategory:
          print("noSuitableRouteForCategory")

      case .routeConfigurationChange:
          print("routeConfigurationChange")

      @unknown default:
          print("default")
      }
}

理解が浅い

  • AVAudioSession.CategoryOptions

参考

オンライン英会話(ラングリッチ)を1年続けて IELTS を受けました

f:id:ie-kau:20190607010212p:plain:w480


こんにちは手段と目的を履き違えることが趣味の @hazumu です。

だーいぶ、書くのが遅れてしまったのですが、去年の1月ぐらいからネット英会話を初めて1年半経ったのでその中間ポイントとしてのまとめと課題を自分なりに整理してみようと思います。

失われた目的とスタート地点

さて、何のためにこの期に及んで英会話を始めたのかというと、昨年の5月頃に facebook の デベロッパーカンファレンスである f8 に行ける機会を頂いたことに帰結します。
f8 に関してはせっかくの機会だし生でマーク・ザッカーバーグのスピーチが聞きたいし、現地で働いてる人に色々話を聞いてみたいと思うようなるなど、久しく錆び付いてた野心が疼いてきたことと真面目に英語を勉強していた高校時代から10年以上経っているので知識の底上げもかねて再勉強してみようと考えたのが全ての始まりです。

もとの英語力でいうと読解・リスニングは大学受験できる程度で学習が止まっていました。スピーキング・ライティングに関しては素人です。

  • 読解・リスニング
    • 大学受験レベル
    • 就職活動時代の TOEIC の残り香少々
  • スピーキング
    • 20代前半でお試しで英会話に通ったことはあるが概ねゴミ
  • ライティング
    • 素人

といったところからのスタート。

f:id:ie-kau:20190607002833j:plain:w300
f8 はとても楽しかった。

そして f8 終了後も当面の目標を失いつつも走り続けているというのが開始1年半後の今です。 今日までを振り返り内省しつつ、そろそろ英語をはじめよかっなって方の参考になれば幸いです。

教材選定

主眼はスピーキングなので、まずはオンライン英会話の教材選定。

www.langrich.com

悩むのも面倒だったし某外資系インターネット企業で腕を鳴らした Hayato-san がなんと3ヶ月で英語を話せるようになったと噂のラングリッチを選択。
1日30分で 6000円 / month と駅前留学的 something like that とかと比べると格安です。 ほかを利用してないので一概に比較はできませんが

良い点

  • 先生がみんな優しい
  • 割と時間の融通が聞く

正直言って始める前は吐くほど緊張するのですが、先生が笑顔、且つフレンドリーで私が連発する意味不明な発言に対しても必死で汲み取る努力をしてくれるので気楽に授業を受けることができています。 

悪い点

  • 特になし

現状、あまりの出来なさにマジギレされようなことも発生してないので特に悪いと感じる点は見当たらないです。 以前は教材が若干少なく感じたのですが、最近動画教材などが増えて様々なジャンルについてディスカッションできるようになったので語彙力の拡張にも使えて満足しています。
この記事を書く前に最後に撮った授業はスミソニアン博物館のアクアマリンに関するディスカッションでした。iridescentという単語を覚えた。

授業の流れ

授業中は雑談をする、恋愛相談される等など勉強になれば何をしてもいいのですが、自分の場合はIELTS(※後述)の試験の前以外は、たいてい動画教材を利用して受講しています。 流れはこんな感じです。

  1. 前日 : 講師と教材を選択して予約
  2. 10分前 : 授業開始に動画教材を一通りみて語彙の確認
  3. 受講(25分)
  4. 終了後10分 : レビューが帰ってくるので確認

これが基本的な流れです。
ただ、中には異常なまでに仲良くなった先生もいたのでその場合は30分他愛もない雑談をしたり愚痴を言ったり聞いたりして30分過ごすってこともしばしば。

開始数ヶ月間のミス

開始3、4ヶ月はただただ受動的に授業を受けていたのですが、当然のことながら全く話せるようになりませんでした 🤯🤯🤪
強いて言えば hello が hell に聞こえるという問題が少し解決した程度。

※流石にこのレベルからは脱却

それもそのはずでアウトプットの機会は手に入れたもの、インプットがないので、「覚える→使う→覚える→使う」といったサイクルが回せず、「知ってる範囲でアウトプット→知ってる範囲でアウトプット」 の悲しみの螺旋となり、使える語彙やフレーズなど知識が全く増えていませんでした。

しょーがないのでインプット厚めにするため、、 ラングリッチと並行でDuo3.0の例文丸暗記プランを遂行することにしました。 なんで Duo3.0かというと、

  • 使われている順の英単語とその英単語をもとに構築された英文が豊富
  • 日常会話で利用されている phrasal verbs(動詞と前置詞の組み合わせのあれ) 多め
  • 家に転がってた

だったからです。

DUO 3.0

DUO 3.0

さすがに一回だけだと覚えきれないので6月〜10月で3周ぐらいしてみました。 この繰り返しの時点で、徐々に表現力が上がってきて日々のラングリッチが楽しくなってくるのを実感しました。また、先生と込み入った話ができるようになりやたらと仲良くなったりし始めたのものこの時期になります。

実力を測りたくなって

普通に息してるだけだと実践の機会があまりないので、2018年の暮れに現状の実力を測りたくなって IELTS を受けることにしました。

www.eiken.or.jp

なぜ TOEFLではないかというと、スピーキングの試験がvs コンピュータではなく vs 人なので笑顔とコミュ力での加点を狙ったという小賢しい理由です。
教材はネットで評判が高かったこの辺を選定。

【音声ダウンロード付】実践IELTS英単語3500

【音声ダウンロード付】実践IELTS英単語3500

育児休暇中の深夜対応時に子供が泣いていない合間をついて薄暗い部屋の中で覚え続けるメンヘラ期(2018年11月)。

Cambridge IELTS 13 General Training Student's Book with Answers with Audio: Authentic Examination Papers (IELTS Practice Tests)

Cambridge IELTS 13 General Training Student's Book with Answers with Audio: Authentic Examination Papers (IELTS Practice Tests)

薄いくせに高い!が、ボリュームは十分。 上記教材に加えて、ラングリッチで IELTSのスピーキング問題を出してもらい、 「aじゃなくて the」、「過去形になっていない」などとにかくボコボコにされながら調整をかけて行きました。

結果

f:id:ie-kau:20190606233935p:plain

中程度のユーザー
不完全だが英語を使う能力を有しており、ほとんどの状況でおおまかな意味を把握することできる。ただし、間違いを犯すことも多い。自身の専門分野では、基本的なコミュニケーションを取ることが可能。

中程度のユーザーになったぞ!!!!!!!!!

はい、何の自慢にもならない点数でした。
とはいえ、1年ぐらいの付け焼き刃で中高生時代に勉強したであろう読解とスピーキングが並んだので気合丸暗記プランは堅調な予感もします。 また、せっかく購入した単語帳も問題集もパーフェクトにやり込めたわけじゃないので今年に入ってもちまちま時間を見つけては進めてみています。

まとめと今後の課題

昨年分の総評としては、ラングリッチでアウトプットの時間を確保しつつも丸暗記の分量をもう少し増やしても良かったかなと思っています。とくに無策でラングリッチに突っ込んでいった1月〜4月は組み合わせでもう少し要領よく勉強できたと思います。

また、1年とちょっと腰を据えて勉強してみて以下の課題が見えているので徐々に調整をかけていければと考えています。

1. 語彙力

IELTS の試験でも日本人が本来得点源とするリーディングで点数を伸ばせなかったことろを見ると語彙力の不足が露呈したのではないかと思います。(もしくは日本語を含めた純粋な読解力がクソかのどちらか。)
加えて、スピーキング時でも自分が使いたい言葉がぱっと出ない事が多い、及び、簡単な英語に翻訳しなおせず詰まることが多々あるのも語彙力の不足に起因するのだと思います。(起因するとかね) 読解力が問題ではないとすると記憶ゲームなので純粋な勉強不足かなと。 勘だけど適当な IELTS か TOEFL の英単語帳を2,3冊覚えたらもうすこし形にはなりそう。

2. ネイティブの雑談を聞けるリスニング力

俗語多めだったり会話のスピードだったりとまだまだ、ネイティブの雑談を聞けるレベルとは程遠いです。 ここ2年ぐらいで洋画を字幕無しである程度理解できるようになりたいですね。とりまラ・ラ・ランドのセリフでも音声ごと丸暗記してみるかとかとか、、、

3. 発音

昨年は明らかに捨ててかかっていたので笑えないレベルでひどいです。 噂では発音できると聞き取れるようになるらしいのでそれを信じてがんばりたいです。(反面、聞けるようになると発音できるという噂もあり、まさにデッドロックな情報も入ってきてるので現代の七不思議に数えたいぐらいです。) ここに関しては、なにが時間帯効率がよい訓練なのかわからないので、いろいろ試したいところです。だれかいいテクニックもってたら教えてください〜

4. ノリ

アメリカで暮らしたことがある人や外資系企業で働いてる人をみると、なんというか、こう、人と壁を作らず話せるというか、そういうノリがうまいですね。海外旅行に言ったらやたら話しかけてくれる人たちのノリです。これだけは、体験にまさる勉強がなさそうなのでいつかチャレンジしたいものですね。もしくは永遠に堀を埋め続けてそこに林檎の木を植えるのもまた一興かもしれません。

1〜3は日本にいても鍛えられると思うので、もう2年ぐらいかけて調整できれば面白そうだなと企んでいます。

おまけ

よくつかう言葉だけど英語にできなかったやつら。

しれっと
As if there was nothing

遠慮する
refrain from

差し控える
withhold

強気
upbeat

多種多様な
miscellaneous

前倒しする
pull in

全力で
flat out

眼精疲労
asthenopia

iOSのApp内課金でプロダクトIDの作成上限を知りたくなったときに見るページ

f:id:ie-kau:20190513160429p:plain:w300

プロダクトIDの作成上限を知りたいけどドキュメントが散ってて発見できないそんなあなたにショートカットをプレゼント!

App 内課金を設定するためのワークフロー

デベロッパアカウント 1 つにつき、アカウント内のすべての App で合計 10,000 個の App 内課金プロダクトを作成できます。また、App Store Connect 内で同一の App として iOS と tvOS がある場合は、両方のバイナリに同じ App 内課金を使用することができます。App 内課金のタイプには、消耗型、非消耗型、自動更新登録、非更新登録の 4 つがあります。

後方参照を利用した replace メモ

f:id:ie-kau:20151019153301j:plain


かなり長い間 JavaScript を書いてる気がするのに、replaceで後方参照が使えることを知らなかったので使い方をメモ。

ユースケース

1234567 というハイフン入れ忘れの郵便番号を 123-4567 というハイフンありに修正するケース

const postalCode = '1234567'.replace(/^([0-9]{3})([0-9]{4})$/, "$1-$2")
console.log(postalCode) // => 123-4567

これはテク

MySQLで特定日からの連続する日付の一覧を作る

f:id:ie-kau:20180616033236j:plain

MySQLで分析するときに、連続する日付の表を仮想的に組み立てたいときってありますよね。

SET @start_day = '2017-04-01';
SELECT DATE_FORMAT(DATE_ADD(@start_day, INTERVAL tmp.series DAY), '%Y-%m-%d') AS day
FROM
(
    SELECT 0 series FROM DUAL WHERE (@num:=-1)*0 UNION ALL
    SELECT @num:=@num+1 FROM `information_schema`.COLUMNS
) AS tmp
HAVING DATE_FORMAT(day, '%Y-%m-%d') <= DATE_FORMAT(CURRENT_DATE(), '%Y-%m-%d');

結果

f:id:ie-kau:20181021003440p:plain

ちなみに

BigQueryだともうちょい簡単

SELECT
  date
FROM UNNEST(GENERATE_DATE_ARRAY('2017-04-01', CURRENT_DATE())) AS date
ORDER BY date;

SQLアンチパターン

SQLアンチパターン

MySQLでのユーザー管理系コマンドまとめ - 追加・権限付与 -

f:id:ie-kau:20180616033236j:plain

行う機会が少なくてどうしても覚えられないユーザー管理系のコマンドまとめ!

ユーザー追加

CREATE USER hazumu

パスワード追加

SET PASSWORD FOR hazumu = PASSWORD('パスワード')

権限確認

SHOW GRANTS FOR hazumu

SELECT権限を与える

GRANT SELECT ON DB名.* TO hazumu

まとめてやる

GRANT ALL ON DB名.* to hazumu@ホスト名 IDENTIFIED BY 'パスワード'

ユーザー一覧確認

SELECT Host, User FROM mysql.user;

ユーザー削除

DROP USER hazumu@ホスト名

詳解MySQL 5.7 止まらぬ進化に乗り遅れないためのテクニカルガイド (NEXT ONE)

詳解MySQL 5.7 止まらぬ進化に乗り遅れないためのテクニカルガイド (NEXT ONE)

どこで起こったかわからない unhandledRejection のコールスタックをキャプチャする

f:id:ie-kau:20161103231112p:plain

すいませんorz...

2017年後半〜2018年前半ブチクソ忙しくて全くブログの更新ができていませんでした!!!!!!!

facebookとかではちまちま発言してるのですが、会社でのサービスづくりに熱中しておりこちら側がおろそかになっていました。
そろそろ復活させるぞ!!!!

ということで復帰記事ですが完全メモ書きです。

Node / Expressでサーバーを運用していると↓みたいな感じで try catch せずに投げ捨てた非同期処理内でエラーを起こしてしまい UnhandledPromiseRejectionWarning が出力されただけで、どこでエラーが発生したかよくわからない状態になってしまうことがあります。

(node:15344) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 10): ReferenceError: hoge is not defined

これでいうと hogeの ReferenceErrorどこでおこっとるんや!!と。

そういうときは、

process.on('unhandledRejection', (reason, p) => {
    console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
})

上記のように、unhandledRejection のイベントをキャプチャしておけば

Unhandled Rejection at: Promise Promise {
  <rejected> ReferenceError: hoge is not defined
    at type (/home/develop/fugafuga.js:725:18)
    at router.post (/home/develop/routes/hogehoge.js:500:7)
    at <anonymous> } reason: ReferenceError: hoge is not defined
    at type (/home/develop/fugafuga.js:725:18)

という感じでコールスタックを取得することがでるようです。